@carthooks/arcubase-cli 0.1.21 → 0.1.23

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.
Files changed (57) hide show
  1. package/bundle/arcubase-admin.mjs +1430 -83
  2. package/bundle/arcubase.mjs +1430 -83
  3. package/dist/generated/command_registry.generated.d.ts +300 -0
  4. package/dist/generated/command_registry.generated.d.ts.map +1 -1
  5. package/dist/generated/command_registry.generated.js +416 -0
  6. package/dist/generated/help_examples.generated.d.ts +116 -0
  7. package/dist/generated/help_examples.generated.d.ts.map +1 -1
  8. package/dist/generated/help_examples.generated.js +184 -0
  9. package/dist/generated/type_index.generated.d.ts +40 -1
  10. package/dist/generated/type_index.generated.d.ts.map +1 -1
  11. package/dist/generated/type_index.generated.js +42 -1
  12. package/dist/generated/zod_registry.generated.d.ts +29 -1
  13. package/dist/generated/zod_registry.generated.d.ts.map +1 -1
  14. package/dist/generated/zod_registry.generated.js +37 -0
  15. package/dist/runtime/dev_sdk_gen.d.ts +9 -0
  16. package/dist/runtime/dev_sdk_gen.d.ts.map +1 -0
  17. package/dist/runtime/dev_sdk_gen.js +319 -0
  18. package/dist/runtime/execute.d.ts.map +1 -1
  19. package/dist/runtime/execute.js +326 -1
  20. package/dist/runtime/zod_registry.d.ts.map +1 -1
  21. package/dist/runtime/zod_registry.js +58 -0
  22. package/package.json +1 -1
  23. package/sdk-dist/api/admin/index.ts +1 -0
  24. package/sdk-dist/api/admin/public-link.ts +48 -0
  25. package/sdk-dist/api/shared-link/form.ts +42 -1
  26. package/sdk-dist/api/user/index.ts +0 -1
  27. package/sdk-dist/docs/runtime-reference/dashboard.md +22 -0
  28. package/sdk-dist/docs/runtime-reference/dev-sdk-gen.md +41 -0
  29. package/sdk-dist/docs/runtime-reference/help-examples/admin/dashboard/update-layout.json +16 -0
  30. package/sdk-dist/docs/runtime-reference/help-examples/admin/widget/create.json +33 -0
  31. package/sdk-dist/docs/runtime-reference/help-examples/admin/widget/preview-data.json +66 -0
  32. package/sdk-dist/docs/runtime-reference/help-examples/admin/widget/update-ingress-options.json +21 -0
  33. package/sdk-dist/docs/runtime-reference/widgets.md +64 -0
  34. package/sdk-dist/generated/command_registry.generated.ts +416 -0
  35. package/sdk-dist/generated/help_examples.generated.ts +184 -0
  36. package/sdk-dist/generated/type_index.generated.ts +42 -1
  37. package/sdk-dist/generated/zod_registry.generated.ts +56 -0
  38. package/sdk-dist/types/app.ts +37 -1
  39. package/sdk-dist/types/common.ts +77 -35
  40. package/sdk-dist/types/index.ts +1 -1
  41. package/sdk-dist/types/public-link.ts +10 -0
  42. package/sdk-dist/types/shared-link.ts +16 -1
  43. package/sdk-dist/types/user-action.ts +1 -43
  44. package/src/generated/command_registry.generated.ts +416 -0
  45. package/src/generated/help_examples.generated.ts +184 -0
  46. package/src/generated/type_index.generated.ts +42 -1
  47. package/src/generated/zod_registry.generated.ts +56 -0
  48. package/src/runtime/dev_sdk_gen.ts +360 -0
  49. package/src/runtime/execute.ts +371 -1
  50. package/src/runtime/zod_registry.ts +58 -0
  51. package/src/tests/command_registry.test.ts +21 -2
  52. package/src/tests/dev_sdk_gen.test.ts +226 -0
  53. package/src/tests/docs_readability.test.ts +15 -0
  54. package/src/tests/execute_validation.test.ts +226 -0
  55. package/src/tests/help.test.ts +86 -0
  56. package/sdk-dist/api/user/copilot.ts +0 -20
  57. package/sdk-dist/types/copilot.ts +0 -34
@@ -297,6 +297,148 @@ var adminCommands = [
297
297
  "queryParams": [],
298
298
  "responseType": "boolean"
299
299
  },
300
+ {
301
+ "scope": "admin",
302
+ "module": "dashboard",
303
+ "functionName": "getDashboardList",
304
+ "commandPath": [
305
+ "dashboard",
306
+ "list"
307
+ ],
308
+ "method": "GET",
309
+ "endpoint": "/api/apps/:app_id/dashboard",
310
+ "pathParams": [
311
+ {
312
+ "param": "app_id",
313
+ "flag": "app-id"
314
+ }
315
+ ],
316
+ "controller": "Dashboard.GetList",
317
+ "requestType": null,
318
+ "queryParams": [],
319
+ "responseType": "DashboardGetListRespVO"
320
+ },
321
+ {
322
+ "scope": "admin",
323
+ "module": "dashboard",
324
+ "functionName": "createDashboard",
325
+ "commandPath": [
326
+ "dashboard",
327
+ "create"
328
+ ],
329
+ "method": "POST",
330
+ "endpoint": "/api/apps/:app_id/dashboard",
331
+ "pathParams": [
332
+ {
333
+ "param": "app_id",
334
+ "flag": "app-id"
335
+ }
336
+ ],
337
+ "controller": "Dashboard.Create",
338
+ "requestType": "DashboardCreateReqVO",
339
+ "queryParams": [],
340
+ "responseType": "DashboardCreateRespVO"
341
+ },
342
+ {
343
+ "scope": "admin",
344
+ "module": "dashboard",
345
+ "functionName": "getDashboardOptions",
346
+ "commandPath": [
347
+ "dashboard",
348
+ "get-options"
349
+ ],
350
+ "method": "GET",
351
+ "endpoint": "/api/apps/:app_id/dashboard/:dashboard_id/options",
352
+ "pathParams": [
353
+ {
354
+ "param": "app_id",
355
+ "flag": "app-id"
356
+ },
357
+ {
358
+ "param": "dashboard_id",
359
+ "flag": "dashboard-id"
360
+ }
361
+ ],
362
+ "controller": "Dashboard.FetchOptions",
363
+ "requestType": null,
364
+ "queryParams": [],
365
+ "responseType": "DashboardFetchOptionsRespVO"
366
+ },
367
+ {
368
+ "scope": "admin",
369
+ "module": "dashboard",
370
+ "functionName": "updateDashboardOptions",
371
+ "commandPath": [
372
+ "dashboard",
373
+ "update-options"
374
+ ],
375
+ "method": "PUT",
376
+ "endpoint": "/api/apps/:app_id/dashboard/:dashboard_id/options",
377
+ "pathParams": [
378
+ {
379
+ "param": "app_id",
380
+ "flag": "app-id"
381
+ },
382
+ {
383
+ "param": "dashboard_id",
384
+ "flag": "dashboard-id"
385
+ }
386
+ ],
387
+ "controller": "Dashboard.UpdateOptions",
388
+ "requestType": "DashboardUpdateOptionsReqVO",
389
+ "queryParams": [],
390
+ "responseType": "DashboardUpdateOptionsRespVO"
391
+ },
392
+ {
393
+ "scope": "admin",
394
+ "module": "dashboard",
395
+ "functionName": "updateDashboardLayout",
396
+ "commandPath": [
397
+ "dashboard",
398
+ "update-layout"
399
+ ],
400
+ "method": "PUT",
401
+ "endpoint": "/api/apps/:app_id/dashboard/:dashboard_id/layout",
402
+ "pathParams": [
403
+ {
404
+ "param": "app_id",
405
+ "flag": "app-id"
406
+ },
407
+ {
408
+ "param": "dashboard_id",
409
+ "flag": "dashboard-id"
410
+ }
411
+ ],
412
+ "controller": "Dashboard.UpdateLayout",
413
+ "requestType": "DashboardUpdateLayoutReqVO",
414
+ "queryParams": [],
415
+ "responseType": "DashboardUpdateLayoutRespVO"
416
+ },
417
+ {
418
+ "scope": "admin",
419
+ "module": "dashboard",
420
+ "functionName": "updateDashboardTitle",
421
+ "commandPath": [
422
+ "dashboard",
423
+ "rename"
424
+ ],
425
+ "method": "PUT",
426
+ "endpoint": "/api/apps/:app_id/dashboard/:dashboard_id/label",
427
+ "pathParams": [
428
+ {
429
+ "param": "app_id",
430
+ "flag": "app-id"
431
+ },
432
+ {
433
+ "param": "dashboard_id",
434
+ "flag": "dashboard-id"
435
+ }
436
+ ],
437
+ "controller": "Dashboard.UpdateTitle",
438
+ "requestType": "DashboardUpdateTitleReqVO",
439
+ "queryParams": [],
440
+ "responseType": "DashboardUpdateTitleRespVO"
441
+ },
300
442
  {
301
443
  "scope": "admin",
302
444
  "module": "table",
@@ -732,6 +874,188 @@ var adminCommands = [
732
874
  "requestType": "EntityWorkflowUpdateReqVO",
733
875
  "queryParams": [],
734
876
  "responseType": "EntityWorkflowUpdateRespVO"
877
+ },
878
+ {
879
+ "scope": "admin",
880
+ "module": "widget",
881
+ "functionName": "widgetsList",
882
+ "commandPath": [
883
+ "widget",
884
+ "list"
885
+ ],
886
+ "method": "GET",
887
+ "endpoint": "/api/apps/:app_id/widgets",
888
+ "pathParams": [
889
+ {
890
+ "param": "app_id",
891
+ "flag": "app-id"
892
+ }
893
+ ],
894
+ "controller": "App.WidgetsList",
895
+ "requestType": null,
896
+ "queryParams": [
897
+ {
898
+ "key": "type",
899
+ "flag": "type",
900
+ "type": "string",
901
+ "hasDefault": true
902
+ },
903
+ {
904
+ "key": "dashboard_id",
905
+ "flag": "dashboard-id",
906
+ "type": "number",
907
+ "hasDefault": true
908
+ },
909
+ {
910
+ "key": "ingress_id",
911
+ "flag": "ingress-id",
912
+ "type": "number",
913
+ "hasDefault": true
914
+ }
915
+ ],
916
+ "responseType": "AppWidgetsListRespVO"
917
+ },
918
+ {
919
+ "scope": "admin",
920
+ "module": "widget",
921
+ "functionName": "getWidgets",
922
+ "commandPath": [
923
+ "widget",
924
+ "get"
925
+ ],
926
+ "method": "GET",
927
+ "endpoint": "/api/apps/:app_id/widgets/:widgets_id",
928
+ "pathParams": [
929
+ {
930
+ "param": "app_id",
931
+ "flag": "app-id"
932
+ },
933
+ {
934
+ "param": "widgets_id",
935
+ "flag": "widget-id"
936
+ }
937
+ ],
938
+ "controller": "App.GetWidgets",
939
+ "requestType": null,
940
+ "queryParams": [],
941
+ "responseType": "AppGetWidgetsRespVO"
942
+ },
943
+ {
944
+ "scope": "admin",
945
+ "module": "widget",
946
+ "functionName": "newWidgets",
947
+ "commandPath": [
948
+ "widget",
949
+ "create"
950
+ ],
951
+ "method": "POST",
952
+ "endpoint": "/api/apps/:app_id/widgets",
953
+ "pathParams": [
954
+ {
955
+ "param": "app_id",
956
+ "flag": "app-id"
957
+ }
958
+ ],
959
+ "controller": "App.NewWidgets",
960
+ "requestType": "AppNewWidgetsReqVO",
961
+ "queryParams": [],
962
+ "responseType": "AppNewWidgetsRespVO"
963
+ },
964
+ {
965
+ "scope": "admin",
966
+ "module": "widget",
967
+ "functionName": "updateWidgets",
968
+ "commandPath": [
969
+ "widget",
970
+ "update"
971
+ ],
972
+ "method": "PUT",
973
+ "endpoint": "/api/apps/:app_id/widgets/:widgets_id",
974
+ "pathParams": [
975
+ {
976
+ "param": "app_id",
977
+ "flag": "app-id"
978
+ },
979
+ {
980
+ "param": "widgets_id",
981
+ "flag": "widget-id"
982
+ }
983
+ ],
984
+ "controller": "App.UpdateWidgets",
985
+ "requestType": "AppUpdateWidgetsReqVO",
986
+ "queryParams": [],
987
+ "responseType": "AppUpdateWidgetsRespVO"
988
+ },
989
+ {
990
+ "scope": "admin",
991
+ "module": "widget",
992
+ "functionName": "updateWidgetsIngressOptions",
993
+ "commandPath": [
994
+ "widget",
995
+ "update-ingress-options"
996
+ ],
997
+ "method": "PUT",
998
+ "endpoint": "/api/apps/:app_id/widgets/:widgets_id/ingress-options",
999
+ "pathParams": [
1000
+ {
1001
+ "param": "app_id",
1002
+ "flag": "app-id"
1003
+ },
1004
+ {
1005
+ "param": "widgets_id",
1006
+ "flag": "widget-id"
1007
+ }
1008
+ ],
1009
+ "controller": "App.UpdateWidgetsIngressOptions",
1010
+ "requestType": "AppUpdateWidgetsIngressOptionsReqVO",
1011
+ "queryParams": [],
1012
+ "responseType": "AppUpdateWidgetsIngressOptionsRespVO"
1013
+ },
1014
+ {
1015
+ "scope": "admin",
1016
+ "module": "widget",
1017
+ "functionName": "previewWidgetsData",
1018
+ "commandPath": [
1019
+ "widget",
1020
+ "preview-data"
1021
+ ],
1022
+ "method": "POST",
1023
+ "endpoint": "/api/apps/:app_id/widgets-preview",
1024
+ "pathParams": [
1025
+ {
1026
+ "param": "app_id",
1027
+ "flag": "app-id"
1028
+ }
1029
+ ],
1030
+ "controller": "App.PreviewWidgetsData",
1031
+ "requestType": "AppPreviewWidgetsDataReqVO",
1032
+ "queryParams": [],
1033
+ "responseType": "AppPreviewWidgetsDataRespVO"
1034
+ },
1035
+ {
1036
+ "scope": "admin",
1037
+ "module": "widget",
1038
+ "functionName": "deleteWidgets",
1039
+ "commandPath": [
1040
+ "widget",
1041
+ "delete"
1042
+ ],
1043
+ "method": "DELETE",
1044
+ "endpoint": "/api/apps/:app_id/widgets/:widgets_id",
1045
+ "pathParams": [
1046
+ {
1047
+ "param": "app_id",
1048
+ "flag": "app-id"
1049
+ },
1050
+ {
1051
+ "param": "widgets_id",
1052
+ "flag": "widget-id"
1053
+ }
1054
+ ],
1055
+ "controller": "App.DeleteWidgets",
1056
+ "requestType": null,
1057
+ "queryParams": [],
1058
+ "responseType": "boolean"
735
1059
  }
736
1060
  ];
737
1061
  var userCommands = [
@@ -758,6 +1082,77 @@ var userCommands = [
758
1082
  ],
759
1083
  "responseType": "GlobalActionEntryRespVO"
760
1084
  },
1085
+ {
1086
+ "scope": "user",
1087
+ "module": "app",
1088
+ "functionName": "getAppDetail",
1089
+ "commandPath": [
1090
+ "app",
1091
+ "get"
1092
+ ],
1093
+ "method": "GET",
1094
+ "endpoint": "/api/apps/:id",
1095
+ "pathParams": [
1096
+ {
1097
+ "param": "id",
1098
+ "flag": "app-id"
1099
+ }
1100
+ ],
1101
+ "controller": "UserAction.AppDetail",
1102
+ "requestType": null,
1103
+ "queryParams": [],
1104
+ "responseType": "AppDetailRespVO"
1105
+ },
1106
+ {
1107
+ "scope": "user",
1108
+ "module": "dashboard",
1109
+ "functionName": "getDashboard",
1110
+ "commandPath": [
1111
+ "dashboard",
1112
+ "get"
1113
+ ],
1114
+ "method": "GET",
1115
+ "endpoint": "/api/dashboard/:app_id/:dashboard_id",
1116
+ "pathParams": [
1117
+ {
1118
+ "param": "app_id",
1119
+ "flag": "app-id"
1120
+ },
1121
+ {
1122
+ "param": "dashboard_id",
1123
+ "flag": "dashboard-id"
1124
+ }
1125
+ ],
1126
+ "controller": "UserAction.DashboardGet",
1127
+ "requestType": null,
1128
+ "queryParams": [],
1129
+ "responseType": "DashboardGetRespVO"
1130
+ },
1131
+ {
1132
+ "scope": "user",
1133
+ "module": "dashboard",
1134
+ "functionName": "getDashboardWidgets",
1135
+ "commandPath": [
1136
+ "dashboard",
1137
+ "widgets"
1138
+ ],
1139
+ "method": "GET",
1140
+ "endpoint": "/api/dashboard/:app_id/:dashboard_id/widgets",
1141
+ "pathParams": [
1142
+ {
1143
+ "param": "app_id",
1144
+ "flag": "app-id"
1145
+ },
1146
+ {
1147
+ "param": "dashboard_id",
1148
+ "flag": "dashboard-id"
1149
+ }
1150
+ ],
1151
+ "controller": "UserAction.DashboardWidgets",
1152
+ "requestType": null,
1153
+ "queryParams": [],
1154
+ "responseType": "DashboardWidgets[]"
1155
+ },
761
1156
  {
762
1157
  "scope": "user",
763
1158
  "module": "table",
@@ -1179,6 +1574,27 @@ var userCommands = [
1179
1574
  "queryParams": [],
1180
1575
  "responseType": "MobileUploadCheckRespVO"
1181
1576
  },
1577
+ {
1578
+ "scope": "user",
1579
+ "module": "widget",
1580
+ "functionName": "fetchWidgetsData",
1581
+ "commandPath": [
1582
+ "widget",
1583
+ "data"
1584
+ ],
1585
+ "method": "POST",
1586
+ "endpoint": "/api/apps/:app_id/widgets-data",
1587
+ "pathParams": [
1588
+ {
1589
+ "param": "app_id",
1590
+ "flag": "app-id"
1591
+ }
1592
+ ],
1593
+ "controller": "UserAction.FetchWidgetsData",
1594
+ "requestType": "FetchWidgetsDataReqVO",
1595
+ "queryParams": [],
1596
+ "responseType": "FetchWidgetsDataRespVO"
1597
+ },
1182
1598
  {
1183
1599
  "scope": "user",
1184
1600
  "module": "profile",
@@ -16117,9 +16533,26 @@ var AppIngressBulkApplyItemVOSchema = external_exports.lazy(() => external_expor
16117
16533
  var AppIngressBulkApplyReqVOSchema = external_exports.lazy(() => external_exports.object({ "dry_run": external_exports.boolean().optional(), "items": external_exports.array(AppIngressBulkApplyItemVOSchema).optional(), "mode": external_exports.string().optional() }).strict());
16118
16534
  var AppIngressCreateReqVOSchema = external_exports.lazy(() => external_exports.object({ "enabled": external_exports.boolean().optional(), "entity_id": external_exports.number().optional(), "icon_name": external_exports.string().optional(), "name": external_exports.string().optional(), "options": EntityIngressOptionsSchema.optional(), "type": external_exports.string().optional(), "url": external_exports.string().optional() }).strict());
16119
16535
  var AppIngressUpdateReqVOSchema = external_exports.lazy(() => external_exports.object({ "enabled": external_exports.boolean().optional(), "name": external_exports.string().optional(), "options": EntityIngressOptionsSchema.optional(), "update": external_exports.array(external_exports.string()).optional() }).strict());
16536
+ var WidgetsTypeCodeSchema = external_exports.lazy(() => external_exports.union([external_exports.literal(1), external_exports.literal(2)]));
16537
+ var WidgetsTypeSchema = external_exports.lazy(() => external_exports.object({ "dashboard_id": external_exports.number().optional(), "ingress_id": external_exports.number().optional(), "type": WidgetsTypeCodeSchema.optional() }).strict());
16538
+ var AppNewWidgetsReqVOSchema = external_exports.lazy(() => external_exports.object({ "options": WidgetsTypeSchema.optional(), "type": external_exports.string().optional() }).strict());
16539
+ var CubeDimensionSchema = external_exports.lazy(() => external_exports.object({ "FieldID": external_exports.number().optional(), "IsField": external_exports.boolean().optional(), "Label": external_exports.string().optional(), "Name": external_exports.string().optional(), "Options": external_exports.record(external_exports.string(), external_exports.any()).optional(), "OrderBy": external_exports.string().optional(), "PropName": external_exports.string().optional() }).strict());
16540
+ var CubeMeasureAggregateSchema = external_exports.lazy(() => external_exports.union([external_exports.literal("sum"), external_exports.literal("avg"), external_exports.literal("max"), external_exports.literal("min"), external_exports.literal("count"), external_exports.literal("distinct_count")]));
16541
+ var CubeMeasureSchema = external_exports.lazy(() => external_exports.object({ "Aggregate": CubeMeasureAggregateSchema.optional(), "FieldID": external_exports.number().optional(), "Label": external_exports.string().optional(), "Name": external_exports.string().optional(), "Options": external_exports.record(external_exports.string(), external_exports.any()).optional(), "OrderBy": external_exports.string().optional() }).strict());
16542
+ var AppPreviewWidgetsDataReqVOSchema = external_exports.lazy(() => external_exports.object({ "conditions": PermitConditionSetSchema.optional(), "dataSource": external_exports.number().optional(), "dataSourceType": external_exports.string().optional(), "dimensions": external_exports.array(CubeDimensionSchema).optional(), "measures": external_exports.array(CubeMeasureSchema).optional() }).strict());
16120
16543
  var GormDeletedAtSchema = external_exports.lazy(() => external_exports.object({ "Time": external_exports.string().optional(), "Valid": external_exports.boolean().optional() }).strict());
16121
16544
  var AppOptionsSchema = external_exports.lazy(() => external_exports.object({ "use_home_dashboard": external_exports.boolean().optional() }).strict());
16122
16545
  var AppUpdateAppReqVOSchema = external_exports.lazy(() => external_exports.object({ "CreatedAt": external_exports.string().optional(), "DeletedAt": GormDeletedAtSchema.optional(), "ID": external_exports.number().optional(), "Options": AppOptionsSchema.optional(), "UpdatedAt": external_exports.string().optional(), "changed": external_exports.array(external_exports.string()).optional(), "has_workflow": external_exports.boolean().optional(), "icon_color": external_exports.string().optional(), "icon_name": external_exports.string().optional(), "name": external_exports.string().optional(), "tenant_id": external_exports.number().optional(), "use_home_dashboard": external_exports.boolean().optional() }).strict());
16546
+ var WidgetsListViewOptionsSchema = external_exports.lazy(() => external_exports.object({ "cond_follow": external_exports.boolean().optional(), "cond_follow_cols": external_exports.array(external_exports.string()).optional(), "cond_follow_tab": external_exports.boolean().optional(), "link": external_exports.record(external_exports.string(), external_exports.any()).optional() }).strict());
16547
+ var AppUpdateWidgetsIngressOptionsReqVOSchema = external_exports.lazy(() => external_exports.object({ "options": WidgetsListViewOptionsSchema.optional() }).strict());
16548
+ var ChartOptionSchema = external_exports.lazy(() => external_exports.object({ "conditions": PermitConditionSetSchema.optional(), "dimensions": external_exports.array(CubeDimensionSchema).optional(), "entity_id": external_exports.number().optional(), "measures": external_exports.array(CubeMeasureSchema).optional(), "options": external_exports.record(external_exports.string(), external_exports.any()).optional(), "type": external_exports.string().optional() }).strict());
16549
+ var WidgetsOptionSchema = external_exports.lazy(() => external_exports.object({ "charts": ChartOptionSchema.optional(), "ingress": WidgetsListViewOptionsSchema.optional(), "render": external_exports.record(external_exports.string(), external_exports.any()).optional() }).strict());
16550
+ var AppUpdateWidgetsReqVOSchema = external_exports.lazy(() => external_exports.object({ "entity_id": external_exports.number().optional(), "options": WidgetsOptionSchema.optional() }).strict());
16551
+ var DashboardCreateReqVOSchema = external_exports.lazy(() => external_exports.object({ "name": external_exports.string().optional() }).strict());
16552
+ var LayoutPositionSchema = external_exports.lazy(() => external_exports.object({ "h": external_exports.number().optional(), "id": external_exports.number().optional(), "w": external_exports.number().optional(), "x": external_exports.number().optional(), "y": external_exports.number().optional() }).strict());
16553
+ var DashboardUpdateLayoutReqVOSchema = external_exports.lazy(() => external_exports.array(LayoutPositionSchema));
16554
+ var DashboardUpdateOptionsReqVOSchema = external_exports.lazy(() => external_exports.object({ "changed": external_exports.array(external_exports.string()).optional(), "i18n_name": external_exports.record(external_exports.string(), external_exports.string()).optional(), "theme": external_exports.object({ "gutter": external_exports.number().optional(), "has_shadow": external_exports.boolean().optional(), "round_corners": external_exports.number().optional() }).strict().optional(), "users": external_exports.array(PermitUserScopeSchema).optional() }).strict());
16555
+ var DashboardUpdateTitleReqVOSchema = external_exports.lazy(() => external_exports.object({ "name": external_exports.string().optional() }).strict());
16123
16556
  var EntityBulkUpdateActionVOSchema = external_exports.lazy(() => external_exports.object({ "number_add": external_exports.number().optional(), "number_mul": external_exports.number().optional(), "number_sub": external_exports.number().optional(), "text_append": external_exports.string().optional(), "text_prepend": external_exports.string().optional(), "text_replace": external_exports.string().optional(), "text_search": external_exports.string().optional(), "type": external_exports.string().optional(), "value": external_exports.any().optional() }).strict());
16124
16557
  var EntityBulkUpdateFieldVOSchema = external_exports.lazy(() => external_exports.object({ "action": EntityBulkUpdateActionVOSchema.optional(), "id": external_exports.number().optional() }).strict());
16125
16558
  var EntityBulkUpdateReqVOSchema = external_exports.lazy(() => external_exports.object({ "fields": external_exports.array(EntityBulkUpdateFieldVOSchema).optional(), "policy_id": external_exports.string().optional() }).strict());
@@ -16168,6 +16601,8 @@ var WorkflowSLAConfigSchema = external_exports.lazy(() => external_exports.objec
16168
16601
  var WorkflowOptionsSchema = external_exports.lazy(() => external_exports.object({ "allow_urge": external_exports.boolean().optional(), "allow_view_diagram": external_exports.boolean().optional(), "auto_approve_rule": WorkflowAutoApproveRuleSchema.optional(), "retract_rule": WorkflowRetractRuleSchema.optional(), "sla": external_exports.array(WorkflowSLAConfigSchema).optional() }).strict());
16169
16602
  var EntityWorkflowDeployReqVOSchema = external_exports.lazy(() => external_exports.object({ "diagram": WorkflowConfigDiagramSchema.optional(), "id": external_exports.number().optional(), "options": WorkflowOptionsSchema.optional() }).strict());
16170
16603
  var EntityWorkflowUpdateReqVOSchema = external_exports.lazy(() => external_exports.object({ "diagram": WorkflowConfigDiagramSchema.optional(), "id": external_exports.number().optional(), "options": WorkflowOptionsSchema.optional() }).strict());
16604
+ var EntityUtilsQueryOrderSchema = external_exports.lazy(() => external_exports.object({ "column": external_exports.string().optional(), "order": external_exports.string().optional() }).strict());
16605
+ var FetchWidgetsDataReqVOSchema = external_exports.lazy(() => external_exports.object({ "dashboard_id": external_exports.number().optional(), "ingress_hash_id": external_exports.string().optional(), "ingress_id": external_exports.number().optional(), "querys": external_exports.object({ "search": external_exports.record(external_exports.string(), external_exports.any()).optional(), "sorts": external_exports.array(EntityUtilsQueryOrderSchema).optional() }).strict().optional(), "type": WidgetsTypeCodeSchema.optional() }).strict());
16171
16606
  var GetUploadTokenReqVOSchema = external_exports.lazy(() => external_exports.object({ "global": external_exports.boolean().optional() }).strict());
16172
16607
  var InsertReqVOSchema = external_exports.lazy(() => external_exports.object({ "fields": external_exports.record(external_exports.string(), external_exports.any()).optional(), "policy_id": external_exports.string().optional() }).strict());
16173
16608
  var MobileUploadCheckReqVOSchema = external_exports.lazy(() => external_exports.object({ "id": external_exports.number().optional(), "ignored": external_exports.record(external_exports.string(), external_exports.boolean()).optional(), "secret": external_exports.string().optional() }).strict());
@@ -16185,7 +16620,15 @@ var bodySchemas = {
16185
16620
  "AppIngressBulkApplyReqVO": AppIngressBulkApplyReqVOSchema,
16186
16621
  "AppIngressCreateReqVO": AppIngressCreateReqVOSchema,
16187
16622
  "AppIngressUpdateReqVO": AppIngressUpdateReqVOSchema,
16623
+ "AppNewWidgetsReqVO": AppNewWidgetsReqVOSchema,
16624
+ "AppPreviewWidgetsDataReqVO": AppPreviewWidgetsDataReqVOSchema,
16188
16625
  "AppUpdateAppReqVO": AppUpdateAppReqVOSchema,
16626
+ "AppUpdateWidgetsIngressOptionsReqVO": AppUpdateWidgetsIngressOptionsReqVOSchema,
16627
+ "AppUpdateWidgetsReqVO": AppUpdateWidgetsReqVOSchema,
16628
+ "DashboardCreateReqVO": DashboardCreateReqVOSchema,
16629
+ "DashboardUpdateLayoutReqVO": DashboardUpdateLayoutReqVOSchema,
16630
+ "DashboardUpdateOptionsReqVO": DashboardUpdateOptionsReqVOSchema,
16631
+ "DashboardUpdateTitleReqVO": DashboardUpdateTitleReqVOSchema,
16189
16632
  "EntityBulkUpdateReqVO": EntityBulkUpdateReqVOSchema,
16190
16633
  "EntityDoActionReqVO": EntityDoActionReqVOSchema,
16191
16634
  "EntityQueryRelationReqVO": EntityQueryRelationReqVOSchema,
@@ -16198,6 +16641,7 @@ var bodySchemas = {
16198
16641
  "EntityWorkflowApproveUsersReqVO": EntityWorkflowApproveUsersReqVOSchema,
16199
16642
  "EntityWorkflowDeployReqVO": EntityWorkflowDeployReqVOSchema,
16200
16643
  "EntityWorkflowUpdateReqVO": EntityWorkflowUpdateReqVOSchema,
16644
+ "FetchWidgetsDataReqVO": FetchWidgetsDataReqVOSchema,
16201
16645
  "GetUploadTokenReqVO": GetUploadTokenReqVOSchema,
16202
16646
  "InsertReqVO": InsertReqVOSchema,
16203
16647
  "MobileUploadCheckReqVO": MobileUploadCheckReqVOSchema,
@@ -16229,10 +16673,47 @@ var typeIndex = {
16229
16673
  "file": "types/ingress.ts",
16230
16674
  "dependencies": []
16231
16675
  },
16676
+ "AppNewWidgetsReqVO": {
16677
+ "file": "types/widgets.ts",
16678
+ "dependencies": []
16679
+ },
16680
+ "AppPreviewWidgetsDataReqVO": {
16681
+ "file": "types/widgets.ts",
16682
+ "dependencies": []
16683
+ },
16232
16684
  "AppUpdateAppReqVO": {
16233
16685
  "file": "types/app.ts",
16234
16686
  "dependencies": []
16235
16687
  },
16688
+ "AppUpdateWidgetsIngressOptionsReqVO": {
16689
+ "file": "types/widgets.ts",
16690
+ "dependencies": []
16691
+ },
16692
+ "AppUpdateWidgetsReqVO": {
16693
+ "file": "types/widgets.ts",
16694
+ "dependencies": []
16695
+ },
16696
+ "DashboardCreateReqVO": {
16697
+ "file": "types/dashboard.ts",
16698
+ "dependencies": []
16699
+ },
16700
+ "DashboardUpdateLayoutReqVO": {
16701
+ "file": "types/dashboard.ts",
16702
+ "dependencies": [
16703
+ {
16704
+ "symbol": "LayoutPosition",
16705
+ "file": "types/dashboard.ts"
16706
+ }
16707
+ ]
16708
+ },
16709
+ "DashboardUpdateOptionsReqVO": {
16710
+ "file": "types/dashboard.ts",
16711
+ "dependencies": []
16712
+ },
16713
+ "DashboardUpdateTitleReqVO": {
16714
+ "file": "types/dashboard.ts",
16715
+ "dependencies": []
16716
+ },
16236
16717
  "EntityBulkUpdateReqVO": {
16237
16718
  "file": "types/user-action.ts",
16238
16719
  "dependencies": []
@@ -16242,7 +16723,7 @@ var typeIndex = {
16242
16723
  "dependencies": []
16243
16724
  },
16244
16725
  "EntityQueryRelationReqVO": {
16245
- "file": "types/user-action.ts",
16726
+ "file": "types/common.ts",
16246
16727
  "dependencies": []
16247
16728
  },
16248
16729
  "EntityQueryReqVO": {
@@ -16281,6 +16762,10 @@ var typeIndex = {
16281
16762
  "file": "types/workflow.ts",
16282
16763
  "dependencies": []
16283
16764
  },
16765
+ "FetchWidgetsDataReqVO": {
16766
+ "file": "types/user-action.ts",
16767
+ "dependencies": []
16768
+ },
16284
16769
  "GetUploadTokenReqVO": {
16285
16770
  "file": "types/user-action.ts",
16286
16771
  "dependencies": []
@@ -17062,11 +17547,31 @@ var conditionDocHint = {
17062
17547
  title: "Condition",
17063
17548
  file: "docs/runtime-reference/condition.md"
17064
17549
  };
17550
+ var dashboardDocHint = {
17551
+ title: "Dashboard",
17552
+ file: "docs/runtime-reference/dashboard.md"
17553
+ };
17554
+ var widgetsDocHint = {
17555
+ title: "Widgets",
17556
+ file: "docs/runtime-reference/widgets.md"
17557
+ };
17065
17558
  var docHintIndex = {
17066
17559
  AppCreateByTenantsReqVO: [
17067
17560
  { title: "Table lifecycle", file: "docs/runtime-reference/table-lifecycle.md" },
17068
17561
  examplesIndexDocHint
17069
17562
  ],
17563
+ AppNewWidgetsReqVO: [
17564
+ widgetsDocHint
17565
+ ],
17566
+ AppPreviewWidgetsDataReqVO: [
17567
+ widgetsDocHint
17568
+ ],
17569
+ AppUpdateWidgetsIngressOptionsReqVO: [
17570
+ widgetsDocHint
17571
+ ],
17572
+ AppUpdateWidgetsReqVO: [
17573
+ widgetsDocHint
17574
+ ],
17070
17575
  AppCreateEntityReqVO: [
17071
17576
  { title: "Table lifecycle", file: "docs/runtime-reference/table-lifecycle.md" },
17072
17577
  { title: "Table schema cheatsheet", file: "docs/runtime-reference/entity-schema.md" },
@@ -17085,6 +17590,19 @@ var docHintIndex = {
17085
17590
  { title: "Access rule", file: "docs/runtime-reference/access-rule.md" },
17086
17591
  examplesIndexDocHint
17087
17592
  ],
17593
+ DashboardCreateReqVO: [
17594
+ dashboardDocHint
17595
+ ],
17596
+ DashboardUpdateLayoutReqVO: [
17597
+ dashboardDocHint,
17598
+ widgetsDocHint
17599
+ ],
17600
+ DashboardUpdateOptionsReqVO: [
17601
+ dashboardDocHint
17602
+ ],
17603
+ DashboardUpdateTitleReqVO: [
17604
+ dashboardDocHint
17605
+ ],
17088
17606
  EntitySaveReqVO: [
17089
17607
  { title: "Table schema cheatsheet", file: "docs/runtime-reference/entity-schema.md" },
17090
17608
  { title: "Field type index", file: "docs/runtime-reference/entity-schema/README.md" },
@@ -17124,6 +17642,9 @@ var docHintIndex = {
17124
17642
  { title: "Search and bulk actions", file: "docs/runtime-reference/search-and-bulk-actions.md" },
17125
17643
  examplesIndexDocHint
17126
17644
  ],
17645
+ FetchWidgetsDataReqVO: [
17646
+ widgetsDocHint
17647
+ ],
17127
17648
  "EntityInvokeBatchOperatorReqVO & InvokeRequestVO": [
17128
17649
  selectionDocHint,
17129
17650
  conditionDocHint,
@@ -17175,6 +17696,21 @@ var commandDocHintIndex = {
17175
17696
  { title: "Table lifecycle", file: "docs/runtime-reference/table-lifecycle.md" },
17176
17697
  examplesIndexDocHint
17177
17698
  ],
17699
+ "admin.dashboard.getDashboardList": [
17700
+ dashboardDocHint
17701
+ ],
17702
+ "admin.dashboard.getDashboardOptions": [
17703
+ dashboardDocHint
17704
+ ],
17705
+ "admin.widget.widgetsList": [
17706
+ widgetsDocHint
17707
+ ],
17708
+ "admin.widget.getWidgets": [
17709
+ widgetsDocHint
17710
+ ],
17711
+ "admin.widget.deleteWidgets": [
17712
+ widgetsDocHint
17713
+ ],
17178
17714
  "admin.app.createEntity": [
17179
17715
  { title: "Table lifecycle", file: "docs/runtime-reference/table-lifecycle.md" },
17180
17716
  examplesIndexDocHint
@@ -17241,6 +17777,13 @@ var commandDocHintIndex = {
17241
17777
  conditionDocHint,
17242
17778
  { title: "Search and bulk actions", file: "docs/runtime-reference/search-and-bulk-actions.md" },
17243
17779
  examplesIndexDocHint
17780
+ ],
17781
+ "user.dashboard.getDashboard": [
17782
+ dashboardDocHint
17783
+ ],
17784
+ "user.dashboard.getDashboardWidgets": [
17785
+ dashboardDocHint,
17786
+ widgetsDocHint
17244
17787
  ]
17245
17788
  };
17246
17789
  function getCommandDocHints(operation, env = process.env) {
@@ -17782,13 +18325,197 @@ var helpExamplesIndex = {
17782
18325
  ]
17783
18326
  }
17784
18327
  },
17785
- "list_options": {}
18328
+ "list_options": {}
18329
+ }
18330
+ },
18331
+ "notes": [
18332
+ "actor means Arcubase role id",
18333
+ 'condition mode "and" and "or" are canonical; legacy "all" also reads as AND',
18334
+ "nested OR uses subset and leaves the wrapper column/operator empty"
18335
+ ]
18336
+ }
18337
+ ]
18338
+ },
18339
+ "admin.dashboard.update-layout": {
18340
+ "command": [
18341
+ "dashboard",
18342
+ "update-layout"
18343
+ ],
18344
+ "examples": [
18345
+ {
18346
+ "title": "place one dashboard widget in the top-left area",
18347
+ "body": [
18348
+ {
18349
+ "id": 2188892001,
18350
+ "x": 0,
18351
+ "y": 0,
18352
+ "w": 12,
18353
+ "h": 6
18354
+ }
18355
+ ],
18356
+ "notes": [
18357
+ "the request body is a top-level array",
18358
+ 'do not wrap the array as {"layout":[...]}'
18359
+ ]
18360
+ }
18361
+ ]
18362
+ },
18363
+ "admin.widget.create": {
18364
+ "command": [
18365
+ "widget",
18366
+ "create"
18367
+ ],
18368
+ "examples": [
18369
+ {
18370
+ "title": "create a dashboard chart widget",
18371
+ "body": {
18372
+ "type": "chart",
18373
+ "options": {
18374
+ "dashboard_id": 2188892001
18375
+ }
18376
+ },
18377
+ "notes": [
18378
+ "do not set options.type by hand",
18379
+ "dashboard_id selects a dashboard widget",
18380
+ "use widget update next to save chart options"
18381
+ ]
18382
+ },
18383
+ {
18384
+ "title": "create an ingress list widget",
18385
+ "body": {
18386
+ "type": "list",
18387
+ "options": {
18388
+ "ingress_id": 2188893001
18389
+ }
18390
+ },
18391
+ "notes": [
18392
+ "ingress_id selects an ingress widget",
18393
+ "do not place ingress widgets with dashboard update-layout"
18394
+ ]
18395
+ }
18396
+ ]
18397
+ },
18398
+ "admin.widget.preview-data": {
18399
+ "command": [
18400
+ "widget",
18401
+ "preview-data"
18402
+ ],
18403
+ "examples": [
18404
+ {
18405
+ "title": "preview dashboard chart data from a table",
18406
+ "body": {
18407
+ "dataSource": 2188891001,
18408
+ "dataSourceType": "entity",
18409
+ "dimensions": [
18410
+ {
18411
+ "IsField": true,
18412
+ "FieldID": 1004,
18413
+ "Name": "Source"
18414
+ }
18415
+ ],
18416
+ "measures": [
18417
+ {
18418
+ "FieldID": 1005,
18419
+ "Aggregate": "sum",
18420
+ "Name": "Total Amount"
18421
+ }
18422
+ ]
18423
+ },
18424
+ "notes": [
18425
+ "preview-data does not accept --widget-id",
18426
+ "do not send widget_id or id in the request body",
18427
+ "copy dimensions and measures from the chart query you want to preview"
18428
+ ]
18429
+ },
18430
+ {
18431
+ "title": "preview count and distinct_count in one grouped chart",
18432
+ "body": {
18433
+ "dataSource": 2188891001,
18434
+ "dataSourceType": "entity",
18435
+ "dimensions": [
18436
+ {
18437
+ "IsField": true,
18438
+ "FieldID": 1004,
18439
+ "Name": "Source"
18440
+ }
18441
+ ],
18442
+ "measures": [
18443
+ {
18444
+ "Aggregate": "count",
18445
+ "Name": "Lead Count"
18446
+ },
18447
+ {
18448
+ "FieldID": 1002,
18449
+ "Aggregate": "distinct_count",
18450
+ "Name": "Distinct Customers"
18451
+ }
18452
+ ]
18453
+ },
18454
+ "notes": [
18455
+ "supported Aggregate values are sum, avg, max, min, count, and distinct_count",
18456
+ "unsupported aggregate names fail local body validation before the request is sent"
18457
+ ]
18458
+ },
18459
+ {
18460
+ "title": "preview filtered distinct_count grouped by source",
18461
+ "body": {
18462
+ "dataSource": 2188891001,
18463
+ "dataSourceType": "entity",
18464
+ "dimensions": [
18465
+ {
18466
+ "IsField": true,
18467
+ "FieldID": 1004,
18468
+ "Name": "Source"
18469
+ }
18470
+ ],
18471
+ "conditions": {
18472
+ "mode": "and",
18473
+ "conditions": [
18474
+ {
18475
+ "column": ":1006",
18476
+ "operator": "$eq",
18477
+ "value": "yes"
18478
+ }
18479
+ ]
18480
+ },
18481
+ "measures": [
18482
+ {
18483
+ "FieldID": 1002,
18484
+ "Aggregate": "distinct_count",
18485
+ "Name": "Distinct Customers"
18486
+ }
18487
+ ]
18488
+ },
18489
+ "notes": [
18490
+ "use conditions, not filters, for chart data filtering",
18491
+ "for saved charts put the same condition set under options.charts.conditions",
18492
+ "do not remove the condition and hand-calculate filtered statistics from row query results"
18493
+ ]
18494
+ }
18495
+ ]
18496
+ },
18497
+ "admin.widget.update-ingress-options": {
18498
+ "command": [
18499
+ "widget",
18500
+ "update-ingress-options"
18501
+ ],
18502
+ "examples": [
18503
+ {
18504
+ "title": "adjust an ingress list widget display configuration",
18505
+ "body": {
18506
+ "options": {
18507
+ "cond_follow": true,
18508
+ "cond_follow_tab": true,
18509
+ "cond_follow_cols": [
18510
+ ":1001",
18511
+ ":1002"
18512
+ ]
17786
18513
  }
17787
18514
  },
17788
18515
  "notes": [
17789
- "actor means Arcubase role id",
17790
- 'condition mode "and" and "or" are canonical; legacy "all" also reads as AND',
17791
- "nested OR uses subset and leaves the wrapper column/operator empty"
18516
+ "use this only for widgets created with options.ingress_id",
18517
+ "do not use dashboard update-layout for ingress widgets",
18518
+ "verify with widget get after updating ingress options"
17792
18519
  ]
17793
18520
  }
17794
18521
  ]
@@ -17935,10 +18662,313 @@ function renderCommandHelpExamples(scope, command) {
17935
18662
  ].join("\n").trimEnd();
17936
18663
  }
17937
18664
 
18665
+ // src/runtime/dev_sdk_gen.ts
18666
+ function isRecord3(value) {
18667
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
18668
+ }
18669
+ function unwrapData(payload) {
18670
+ return isRecord3(payload) && "data" in payload ? payload.data : payload;
18671
+ }
18672
+ function toPascalCase(value) {
18673
+ const words = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^A-Za-z0-9]+/).filter(Boolean);
18674
+ if (words.length === 0) return "Entity";
18675
+ return words.map((word) => `${word[0].toUpperCase()}${word.slice(1)}`).join("");
18676
+ }
18677
+ function toCamelCase(value) {
18678
+ const pascal = toPascalCase(value);
18679
+ return `${pascal[0].toLowerCase()}${pascal.slice(1)}`;
18680
+ }
18681
+ function sanitizeEntityKey(entity) {
18682
+ const fallback = entity.sdkName || `entity_${entity.id}`;
18683
+ return toCamelCase(fallback) === "entity" ? `entity${entity.id}` : toCamelCase(fallback);
18684
+ }
18685
+ function normalizeFieldType(type) {
18686
+ switch (type) {
18687
+ case "number":
18688
+ return "number";
18689
+ case "boolean":
18690
+ return "boolean";
18691
+ case "select":
18692
+ case "radio":
18693
+ case "checkbox":
18694
+ case "status":
18695
+ return "number | string";
18696
+ case "file":
18697
+ case "image":
18698
+ case "member":
18699
+ case "members":
18700
+ case "department":
18701
+ case "departments":
18702
+ case "linkto":
18703
+ case "relation":
18704
+ case "relationfield":
18705
+ case "subform":
18706
+ return "unknown";
18707
+ default:
18708
+ return "string";
18709
+ }
18710
+ }
18711
+ function normalizeEntities(payload) {
18712
+ const root = unwrapData(payload);
18713
+ if (!isRecord3(root)) {
18714
+ throw new CLIError("SDK_GEN_INVALID_SCHEMA", "sdk-gen expected an app detail object", 2);
18715
+ }
18716
+ const appId = typeof root.id === "number" ? root.id : typeof root.app_id === "number" ? root.app_id : void 0;
18717
+ if (!appId) {
18718
+ throw new CLIError("SDK_GEN_APP_ID_REQUIRED", "sdk-gen expected app id in app detail response", 2);
18719
+ }
18720
+ const sourceEntities = Array.isArray(root.entities) ? root.entities : Array.isArray(root.tables) ? root.tables : Array.isArray(root.entitys) ? root.entitys : [];
18721
+ const entities = sourceEntities.filter((item) => isRecord3(item)).filter((item) => typeof item.id === "number" && typeof item.name === "string").map((item) => {
18722
+ const fields = Array.isArray(item.fields) ? item.fields.filter((field) => isRecord3(field)).filter((field) => typeof field.id === "number" && typeof field.label === "string" && typeof field.type === "string").map((field) => ({
18723
+ id: field.id,
18724
+ label: field.label,
18725
+ key: typeof field.key === "string" ? field.key.trim() : "",
18726
+ type: field.type,
18727
+ required: field.required === true,
18728
+ options: isRecord3(field.options) ? field.options : void 0
18729
+ })) : [];
18730
+ const entity = {
18731
+ appId,
18732
+ id: item.id,
18733
+ name: item.name,
18734
+ sdkName: typeof item.key === "string" && item.key.trim() ? item.key.trim() : "",
18735
+ fields
18736
+ };
18737
+ entity.sdkName = sanitizeEntityKey(entity);
18738
+ return entity;
18739
+ });
18740
+ if (entities.length === 0) {
18741
+ throw new CLIError("SDK_GEN_NO_ENTITIES", "sdk-gen could not find entities in app detail response", 2);
18742
+ }
18743
+ validateEntities(entities);
18744
+ return entities;
18745
+ }
18746
+ function validateEntities(entities) {
18747
+ const entityKeys = /* @__PURE__ */ new Set();
18748
+ for (const entity of entities) {
18749
+ if (entityKeys.has(entity.sdkName)) {
18750
+ throw new CLIError("SDK_GEN_DUPLICATE_ENTITY_KEY", `duplicate generated entity key: ${entity.sdkName}`, 2);
18751
+ }
18752
+ entityKeys.add(entity.sdkName);
18753
+ const fieldKeys = /* @__PURE__ */ new Set();
18754
+ for (const field of entity.fields) {
18755
+ if (!field.key) {
18756
+ throw new CLIError("SDK_GEN_FIELD_KEY_REQUIRED", `field.key is required for ${entity.name}.${field.label} (${field.id})`, 2);
18757
+ }
18758
+ if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(field.key)) {
18759
+ throw new CLIError("SDK_GEN_INVALID_FIELD_KEY", `field.key must be a TypeScript identifier: ${entity.name}.${field.key}`, 2);
18760
+ }
18761
+ if (fieldKeys.has(field.key)) {
18762
+ throw new CLIError("SDK_GEN_DUPLICATE_FIELD_KEY", `duplicate field.key in ${entity.name}: ${field.key}`, 2);
18763
+ }
18764
+ fieldKeys.add(field.key);
18765
+ }
18766
+ }
18767
+ }
18768
+ function emitRuntime() {
18769
+ return `export type ArcubaseSdkConfig = {
18770
+ baseURL: string
18771
+ accessToken?: string
18772
+ refreshToken?: string
18773
+ }
18774
+
18775
+ export type ArcubaseRow<TFields> = {
18776
+ id: number
18777
+ title?: string
18778
+ fields: TFields
18779
+ raw: Record<string, any>
18780
+ }
18781
+
18782
+ export type ArcubaseRuntime = {
18783
+ config: ArcubaseSdkConfig
18784
+ request<T>(method: string, endpoint: string, body?: unknown): Promise<T>
18785
+ }
18786
+
18787
+ type ArcubaseEnvelope<T> = {
18788
+ data?: T
18789
+ error?: { message?: string; key?: string; type?: string }
18790
+ }
18791
+
18792
+ export function createRuntime(config: ArcubaseSdkConfig): ArcubaseRuntime {
18793
+ let accessToken = config.accessToken ?? ''
18794
+ let refreshToken = config.refreshToken ?? ''
18795
+
18796
+ async function request<T>(method: string, endpoint: string, body?: unknown): Promise<T> {
18797
+ const baseURL = config.baseURL.endsWith('/') ? config.baseURL : \`\${config.baseURL}/\`
18798
+ const response = await fetch(new URL(endpoint.replace(/^\\/+/, ''), baseURL).toString(), {
18799
+ method,
18800
+ headers: {
18801
+ 'Content-Type': 'application/json',
18802
+ ...(accessToken ? { Authorization: \`Bearer \${accessToken}\` } : {}),
18803
+ },
18804
+ body: body === undefined ? undefined : JSON.stringify(body),
18805
+ })
18806
+ const payload = await response.json().catch(() => null) as ArcubaseEnvelope<T> | null
18807
+ if (!response.ok || payload?.error) {
18808
+ throw new Error(payload?.error?.message ?? \`Arcubase request failed: \${response.status}\`)
18809
+ }
18810
+ return payload?.data as T
18811
+ }
18812
+
18813
+ return {
18814
+ config: { ...config, accessToken, refreshToken },
18815
+ request,
18816
+ }
18817
+ }
18818
+ `;
18819
+ }
18820
+ function emitSchema(entities) {
18821
+ const schema = {
18822
+ entities: Object.fromEntries(entities.map((entity) => [
18823
+ entity.sdkName,
18824
+ {
18825
+ entityId: entity.id,
18826
+ name: entity.name,
18827
+ fields: Object.fromEntries(entity.fields.map((field) => [
18828
+ field.key,
18829
+ {
18830
+ fieldId: field.id,
18831
+ label: field.label,
18832
+ type: field.type,
18833
+ required: field.required
18834
+ }
18835
+ ]))
18836
+ }
18837
+ ]))
18838
+ };
18839
+ return `export const arcubaseSchema = ${JSON.stringify(schema, null, 2)} as const
18840
+
18841
+ export type ArcubaseEntityKey = keyof typeof arcubaseSchema.entities
18842
+ `;
18843
+ }
18844
+ function emitEntity(entity) {
18845
+ const typeName = toPascalCase(entity.sdkName);
18846
+ const fieldLines = entity.fields.map((field) => {
18847
+ const optional2 = field.required ? "" : "?";
18848
+ return ` ${field.key}${optional2}: ${normalizeFieldType(field.type)}`;
18849
+ });
18850
+ const fieldMapLines = entity.fields.map((field) => ` ${field.key}: ${field.id},`);
18851
+ return `import type { ArcubaseRuntime, ArcubaseRow } from '../runtime.js'
18852
+
18853
+ export type ${typeName}Fields = {
18854
+ ${fieldLines.join("\n")}
18855
+ }
18856
+
18857
+ export type ${typeName}CreateInput = ${typeName}Fields
18858
+ export type ${typeName}UpdateInput = Partial<${typeName}Fields>
18859
+
18860
+ const entityId = ${entity.id}
18861
+ const fieldIds = {
18862
+ ${fieldMapLines.join("\n")}
18863
+ } as const
18864
+
18865
+ function toArcubaseFields(fields: Partial<${typeName}Fields>): Record<string, any> {
18866
+ const out: Record<string, any> = {}
18867
+ for (const [key, value] of Object.entries(fields)) {
18868
+ if (value === undefined) continue
18869
+ const fieldId = fieldIds[key as keyof typeof fieldIds]
18870
+ if (!fieldId) {
18871
+ throw new Error(\`Unknown ${entity.sdkName} field: \${key}\`)
18872
+ }
18873
+ out[String(fieldId)] = value
18874
+ }
18875
+ return out
18876
+ }
18877
+
18878
+ function fromArcubaseFields(raw: Record<string, any> | undefined): ${typeName}Fields {
18879
+ const out: Record<string, any> = {}
18880
+ const source = raw ?? {}
18881
+ for (const [key, fieldId] of Object.entries(fieldIds)) {
18882
+ if (String(fieldId) in source) {
18883
+ out[key] = source[String(fieldId)]
18884
+ }
18885
+ }
18886
+ return out as ${typeName}Fields
18887
+ }
18888
+
18889
+ function mapRow(raw: Record<string, any>): ArcubaseRow<${typeName}Fields> {
18890
+ return {
18891
+ id: Number(raw.id),
18892
+ title: typeof raw.title === 'string' ? raw.title : undefined,
18893
+ fields: fromArcubaseFields(raw.fields),
18894
+ raw,
18895
+ }
18896
+ }
18897
+
18898
+ export function create${typeName}SDK(runtime: ArcubaseRuntime) {
18899
+ return {
18900
+ async create(fields: ${typeName}CreateInput): Promise<number> {
18901
+ return runtime.request<number>('POST', \`/entity/${entity.appId}/\${entityId}/insert\`, {
18902
+ fields: toArcubaseFields(fields),
18903
+ })
18904
+ },
18905
+
18906
+ async update(rowId: string | number, fields: ${typeName}UpdateInput): Promise<boolean> {
18907
+ const data = toArcubaseFields(fields)
18908
+ return runtime.request<boolean>('PUT', \`/entity/${entity.appId}/\${entityId}/row/\${rowId}\`, {
18909
+ data,
18910
+ changed_fields: Object.keys(data).map((fieldId) => Number(fieldId)),
18911
+ })
18912
+ },
18913
+
18914
+ async get(rowId: string | number): Promise<ArcubaseRow<${typeName}Fields>> {
18915
+ const data = await runtime.request<{ record?: Record<string, any> }>('GET', \`/entity/${entity.appId}/\${entityId}/row/\${rowId}\`)
18916
+ return mapRow(data.record ?? {})
18917
+ },
18918
+
18919
+ async query(params: { limit?: number; offset?: number; search?: Record<string, any> } = {}): Promise<{ items: ArcubaseRow<${typeName}Fields>[]; total?: number }> {
18920
+ const data = await runtime.request<{ items?: Record<string, any>[]; total?: number }>('POST', \`/entity/${entity.appId}/\${entityId}/data-query\`, params)
18921
+ return {
18922
+ items: (data.items ?? []).map(mapRow),
18923
+ total: data.total,
18924
+ }
18925
+ },
18926
+ }
18927
+ }
18928
+ `;
18929
+ }
18930
+ function emitClient(entities) {
18931
+ const imports = entities.map((entity) => {
18932
+ const typeName = toPascalCase(entity.sdkName);
18933
+ return `import { create${typeName}SDK } from './entities/${entity.sdkName}.js'`;
18934
+ });
18935
+ const properties = entities.map((entity) => ` ${entity.sdkName}: create${toPascalCase(entity.sdkName)}SDK(runtime),`);
18936
+ return `import { createRuntime, type ArcubaseSdkConfig } from './runtime.js'
18937
+ ${imports.join("\n")}
18938
+
18939
+ export function createArcubaseSdk(config: ArcubaseSdkConfig) {
18940
+ const runtime = createRuntime(config)
18941
+ return {
18942
+ ${properties.join("\n")}
18943
+ }
18944
+ }
18945
+ `;
18946
+ }
18947
+ function emitIndex(entities) {
18948
+ return `export { createArcubaseSdk } from './client.js'
18949
+ export type { ArcubaseSdkConfig, ArcubaseRow } from './runtime.js'
18950
+ export { arcubaseSchema } from './schema.js'
18951
+ ${entities.map((entity) => `export type { ${toPascalCase(entity.sdkName)}Fields, ${toPascalCase(entity.sdkName)}CreateInput, ${toPascalCase(entity.sdkName)}UpdateInput } from './entities/${entity.sdkName}.js'`).join("\n")}
18952
+ `;
18953
+ }
18954
+ function generateArcubaseProjectSDK(payload) {
18955
+ const entities = normalizeEntities(payload);
18956
+ return {
18957
+ files: [
18958
+ { path: "runtime.ts", contents: emitRuntime() },
18959
+ { path: "schema.ts", contents: emitSchema(entities) },
18960
+ ...entities.map((entity) => ({ path: `entities/${entity.sdkName}.ts`, contents: emitEntity(entity) })),
18961
+ { path: "client.ts", contents: emitClient(entities) },
18962
+ { path: "index.ts", contents: emitIndex(entities) }
18963
+ ]
18964
+ };
18965
+ }
18966
+
17938
18967
  // src/runtime/execute.ts
17939
18968
  function renderRootHelp(scope) {
17940
18969
  const binary = scope === "admin" ? "arcubase-admin" : "arcubase";
17941
- const items = listModules(scope).map((item) => ` - ${item}`);
18970
+ const modules = scope === "admin" ? [...listModules(scope), "dev"].sort() : listModules(scope);
18971
+ const items = modules.map((item) => ` - ${item}`);
17942
18972
  return [
17943
18973
  `${binary} <command> [subcommand] [flags]`,
17944
18974
  "",
@@ -17949,6 +18979,16 @@ function renderRootHelp(scope) {
17949
18979
  ...items
17950
18980
  ].join("\n");
17951
18981
  }
18982
+ function renderDevModuleHelp() {
18983
+ return [
18984
+ "arcubase-admin dev <command> [flags]",
18985
+ "",
18986
+ "developer commands for local project tooling",
18987
+ "",
18988
+ "commands:",
18989
+ " - sdk-gen"
18990
+ ].join("\n");
18991
+ }
17952
18992
  function renderModuleHelp(scope, moduleName, env = process.env) {
17953
18993
  const items = listModuleCommands(scope, moduleName);
17954
18994
  if (items.length === 0) {
@@ -18126,6 +19166,41 @@ function getFixedValue2(value) {
18126
19166
  const fixedValue = value.fixedValue;
18127
19167
  return typeof fixedValue === "string" ? fixedValue : void 0;
18128
19168
  }
19169
+ function isDevSDKGenCommand(scope, moduleName, commandName) {
19170
+ return scope === "admin" && moduleName === "dev" && commandName === "sdk-gen";
19171
+ }
19172
+ function validateDevSDKGenFlags(flags) {
19173
+ const allowed = /* @__PURE__ */ new Set(["help", "app-id", "out"]);
19174
+ for (const flag of Object.keys(flags)) {
19175
+ if (!allowed.has(flag)) {
19176
+ throw new CLIError("UNKNOWN_FLAG", `unknown flag --${flag} for dev sdk-gen`, 2, {
19177
+ operation: "dev sdk-gen",
19178
+ hint: "run dev sdk-gen --help for the supported flags"
19179
+ });
19180
+ }
19181
+ }
19182
+ }
19183
+ function renderDevSDKGenHelp() {
19184
+ return [
19185
+ "arcubase-admin dev sdk-gen",
19186
+ "method: local generator",
19187
+ "endpoint: /apps/:app_id",
19188
+ "body: none",
19189
+ "path flags: --app-id",
19190
+ "flags: --out",
19191
+ "",
19192
+ "generates typed TypeScript source for the current Web project",
19193
+ "",
19194
+ "example:",
19195
+ " - arcubase-admin dev sdk-gen --app-id <app_id> --out src/arcubase",
19196
+ "",
19197
+ "requirements:",
19198
+ " - missing field.key values are initialized through admin auth as field<id>",
19199
+ " - existing field.key values must be stable unique TypeScript identifiers",
19200
+ " - entity property names use entity.key when available, otherwise a stable entity<id> fallback",
19201
+ " - generated code accepts createArcubaseSdk({ baseURL, accessToken, refreshToken })"
19202
+ ].join("\n");
19203
+ }
18129
19204
  function resolveEndpoint(command, flags) {
18130
19205
  let resolved = command.endpoint;
18131
19206
  for (const mapping of command.pathParams) {
@@ -18222,7 +19297,7 @@ function effectiveQueryParams(command) {
18222
19297
  return true;
18223
19298
  });
18224
19299
  }
18225
- function isRecord3(value) {
19300
+ function isRecord4(value) {
18226
19301
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
18227
19302
  }
18228
19303
  function stringifyUpstreamBody(value) {
@@ -18235,18 +19310,18 @@ function stringifyUpstreamBody(value) {
18235
19310
  }
18236
19311
  }
18237
19312
  function extractTraceID(value) {
18238
- if (!isRecord3(value)) return void 0;
19313
+ if (!isRecord4(value)) return void 0;
18239
19314
  if (typeof value.trace_id === "string") return value.trace_id;
18240
19315
  if (typeof value.request_id === "string") return value.request_id;
18241
19316
  return void 0;
18242
19317
  }
18243
19318
  function upstreamErrorMessage(value) {
18244
- if (isRecord3(value) && typeof value.message === "string") return value.message;
19319
+ if (isRecord4(value) && typeof value.message === "string") return value.message;
18245
19320
  if (typeof value === "string") return value;
18246
19321
  return stringifyUpstreamBody(value);
18247
19322
  }
18248
19323
  function throwUpstreamHTTPError(endpoint, method, response, parsedResponse) {
18249
- const upstreamError = isRecord3(parsedResponse) && parsedResponse.error ? parsedResponse.error : void 0;
19324
+ const upstreamError = isRecord4(parsedResponse) && parsedResponse.error ? parsedResponse.error : void 0;
18250
19325
  const body = stringifyUpstreamBody(parsedResponse);
18251
19326
  throw new CLIError(
18252
19327
  "UPSTREAM_REQUEST_FAILED",
@@ -18274,11 +19349,11 @@ async function fetchUpstream(url2, init, endpoint, method, fetchImpl) {
18274
19349
  }
18275
19350
  }
18276
19351
  function extractEntityFields(payload) {
18277
- const candidate = isRecord3(payload) && isRecord3(payload.data) ? payload.data : payload;
18278
- if (!isRecord3(candidate) || !Array.isArray(candidate.fields)) {
19352
+ const candidate = isRecord4(payload) && isRecord4(payload.data) ? payload.data : payload;
19353
+ if (!isRecord4(candidate) || !Array.isArray(candidate.fields)) {
18279
19354
  return [];
18280
19355
  }
18281
- return candidate.fields.filter((item) => isRecord3(item)).filter((item) => typeof item.id === "number" && typeof item.type === "string").map((item) => ({
19356
+ return candidate.fields.filter((item) => isRecord4(item)).filter((item) => typeof item.id === "number" && typeof item.type === "string").map((item) => ({
18282
19357
  id: item.id,
18283
19358
  type: item.type,
18284
19359
  label: typeof item.label === "string" ? item.label : void 0
@@ -18301,7 +19376,7 @@ async function fetchEntityFields(runtimeEnv, appId, entityId, fetchImpl) {
18301
19376
  if (!response.ok) {
18302
19377
  throwUpstreamHTTPError(endpoint, "GET", response, parsedResponse);
18303
19378
  }
18304
- if (isRecord3(parsedResponse) && parsedResponse.error) {
19379
+ if (isRecord4(parsedResponse) && parsedResponse.error) {
18305
19380
  const upstreamError = parsedResponse.error;
18306
19381
  const upstreamMessage = upstreamErrorMessage(upstreamError);
18307
19382
  throw new CLIError("UPSTREAM_BODY_ERROR", upstreamMessage, 1, {
@@ -18318,7 +19393,7 @@ function looksLikeLocalFilePath(value) {
18318
19393
  return value.startsWith("./") || value.startsWith("../") || value.startsWith("/") || value.startsWith("~/") || /\.(pdf|png|jpe?g|gif|webp|bmp|svg|heic|txt|csv|xlsx?|docx?|pptx?|zip)$/i.test(value);
18319
19394
  }
18320
19395
  function isValidUploadEntry(value) {
18321
- if (!isRecord3(value)) {
19396
+ if (!isRecord4(value)) {
18322
19397
  return false;
18323
19398
  }
18324
19399
  const hasUploadId = typeof value.upload_id === "number" || typeof value.upload_id === "string";
@@ -18326,11 +19401,11 @@ function isValidUploadEntry(value) {
18326
19401
  return (hasUploadId || hasAssetsId) && typeof value.file === "string" && typeof value.file_name === "string";
18327
19402
  }
18328
19403
  async function validateFileFieldPayloads(scope, command, runtimeEnv, flags, body, fetchImpl) {
18329
- if (!isRecord3(body)) {
19404
+ if (!isRecord4(body)) {
18330
19405
  return;
18331
19406
  }
18332
19407
  const container = command.functionName === "updateEntityRow" ? body.data : body.fields;
18333
- if (!isRecord3(container)) {
19408
+ if (!isRecord4(container)) {
18334
19409
  return;
18335
19410
  }
18336
19411
  const appId = flagValue(flags, "app-id");
@@ -18362,7 +19437,7 @@ async function validateFileFieldPayloads(scope, command, runtimeEnv, flags, body
18362
19437
  ]
18363
19438
  });
18364
19439
  }
18365
- if (isRecord3(value)) {
19440
+ if (isRecord4(value)) {
18366
19441
  const guidance = `${fieldName} must be an upload value array. Use the upload token flow and pass the returned array directly`;
18367
19442
  throw new CLIError("BODY_VALIDATION_FAILED", guidance, 2, {
18368
19443
  operation: `${scope}.${command.module}.${command.functionName}`,
@@ -18475,6 +19550,12 @@ function isTableSchemaCommand(scope, command) {
18475
19550
  function isAccessRuleCommand(scope, command) {
18476
19551
  return scope === "admin" && command.commandPath[0] === "access-rule";
18477
19552
  }
19553
+ function isWidgetPreviewDataCommand(scope, command) {
19554
+ return scope === "admin" && command.commandPath[0] === "widget" && command.commandPath[1] === "preview-data";
19555
+ }
19556
+ function isWidgetUpdateCommand(scope, command) {
19557
+ return scope === "admin" && command.commandPath[0] === "widget" && command.commandPath[1] === "update";
19558
+ }
18478
19559
  function isAccessRuleUpdateCommand(scope, command) {
18479
19560
  return scope === "admin" && command.commandPath[0] === "access-rule" && command.commandPath[1] === "update";
18480
19561
  }
@@ -18771,6 +19852,91 @@ function buildBodyGuidance(requestType) {
18771
19852
  ]
18772
19853
  };
18773
19854
  }
19855
+ if (requestType === "AppPreviewWidgetsDataReqVO") {
19856
+ return {
19857
+ shapeHint: {
19858
+ dataSource: 2188891001,
19859
+ dataSourceType: "entity",
19860
+ dimensions: [{ IsField: true, FieldID: 1004, Name: "Source" }],
19861
+ measures: [{ FieldID: 1005, Aggregate: "sum", Name: "Total Amount" }],
19862
+ conditions: { mode: "and", conditions: [{ column: ":1006", operator: "$eq", value: "yes" }] }
19863
+ },
19864
+ commonMistakes: [
19865
+ "widget preview-data body is the chart query itself",
19866
+ "do not send a saved widget object with id, entity_id, or options",
19867
+ "field dimensions with FieldID must set IsField:true",
19868
+ "use conditions, not filters, for chart data filtering",
19869
+ "do not retry without conditions and then hand-calculate filtered statistics",
19870
+ "unsupported aggregates are invalid; use sum, avg, max, min, count, or distinct_count"
19871
+ ],
19872
+ suggestions: [
19873
+ `retry with: arcubase-admin widget preview-data --app-id <app_id> --body-json '{"dataSource":<table_id>,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":<field_id>,"Name":"Source"}],"measures":[{"FieldID":<number_field_id>,"Aggregate":"sum","Name":"Total Amount"}]}'`,
19874
+ `conditional stats: arcubase-admin widget preview-data --app-id <app_id> --body-json '{"dataSource":<table_id>,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":<source_field_id>,"Name":"Source"}],"conditions":{"mode":"and","conditions":[{"column":":1006","operator":"$eq","value":"yes"}]},"measures":[{"FieldID":<customer_field_id>,"Aggregate":"distinct_count","Name":"Distinct Customers"}]}'`
19875
+ ]
19876
+ };
19877
+ }
19878
+ if (requestType === "AppNewWidgetsReqVO") {
19879
+ return {
19880
+ shapeHint: {
19881
+ type: "list",
19882
+ options: { ingress_id: 2188893001 }
19883
+ },
19884
+ commonMistakes: [
19885
+ "dashboard widgets use options.dashboard_id",
19886
+ "ingress widgets use options.ingress_id",
19887
+ "do not put entity_id at body top level or under options when creating a widget",
19888
+ "after creating an ingress widget, use widget update-ingress-options to adjust display configuration"
19889
+ ],
19890
+ suggestions: [
19891
+ `dashboard chart: arcubase-admin widget create --app-id <app_id> --body-json '{"type":"chart","options":{"dashboard_id":<dashboard_id>}}'`,
19892
+ `ingress list: arcubase-admin widget create --app-id <app_id> --body-json '{"type":"list","options":{"ingress_id":<ingress_id>}}'`
19893
+ ]
19894
+ };
19895
+ }
19896
+ if (requestType === "AppUpdateWidgetsReqVO") {
19897
+ return {
19898
+ shapeHint: {
19899
+ entity_id: 2188891001,
19900
+ options: {
19901
+ charts: {
19902
+ entity_id: 2188891001,
19903
+ dimensions: [{ IsField: true, FieldID: 1004, Name: "Source" }],
19904
+ measures: [{ FieldID: 1005, Aggregate: "sum", Name: "Total Amount" }],
19905
+ conditions: { mode: "and", conditions: [{ column: ":1006", operator: "$eq", value: "yes" }] },
19906
+ type: "bar"
19907
+ }
19908
+ }
19909
+ },
19910
+ commonMistakes: [
19911
+ "dashboard chart config belongs in body.options.charts",
19912
+ "ingress/list display settings use widget update-ingress-options, not widget update",
19913
+ "do not put ingress_id, list, default_cols, page_size, or entry display settings in widget update",
19914
+ "field dimensions with FieldID must set IsField:true",
19915
+ "use options.charts.conditions, not filters, for chart data filtering",
19916
+ "do not retry without conditions and then hand-calculate filtered statistics",
19917
+ "verify persistence with widget get or widget list after update"
19918
+ ],
19919
+ suggestions: [
19920
+ `dashboard chart: arcubase-admin widget update --app-id <app_id> --widget-id <widget_id> --body-json '{"entity_id":<table_id>,"options":{"charts":{"entity_id":<table_id>,"dimensions":[{"IsField":true,"FieldID":<field_id>,"Name":"Source"}],"measures":[{"FieldID":<number_field_id>,"Aggregate":"sum","Name":"Total Amount"}],"type":"bar"}}}'`,
19921
+ `ingress list display: arcubase-admin widget update-ingress-options --app-id <app_id> --widget-id <widget_id> --body-json '{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}'`
19922
+ ]
19923
+ };
19924
+ }
19925
+ if (requestType === "AppUpdateWidgetsIngressOptionsReqVO") {
19926
+ return {
19927
+ shapeHint: {
19928
+ options: { cond_follow: true, cond_follow_tab: true, cond_follow_cols: [":1001", ":1002"] }
19929
+ },
19930
+ commonMistakes: [
19931
+ "widget update-ingress-options is for ingress widgets, not dashboard chart widgets",
19932
+ "put display settings under body.options",
19933
+ "verify the ingress widget with widget get after update"
19934
+ ],
19935
+ suggestions: [
19936
+ `retry with: arcubase-admin widget update-ingress-options --app-id <app_id> --widget-id <widget_id> --body-json '{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}'`
19937
+ ]
19938
+ };
19939
+ }
18774
19940
  return {};
18775
19941
  }
18776
19942
  function buildBodyValidationDetails(scope, command, requestType, issues, env = process.env) {
@@ -18790,7 +19956,7 @@ function throwBodyValidationFailure(message, requestType, path3, scope, command,
18790
19956
  throw new CLIError("BODY_VALIDATION_FAILED", message, 2, buildBodyValidationDetails(scope, command, requestType, [{ path: path3, message }], env));
18791
19957
  }
18792
19958
  function requireTableCreateSchemaBody(scope, command, body, env) {
18793
- if (!isRecord3(body)) {
19959
+ if (!isRecord4(body)) {
18794
19960
  throwBodyValidationFailure(
18795
19961
  "table create requires a JSON object with name, fields, field_id_seq, layout, options, and workflow_enabled",
18796
19962
  "AppCreateEntityReqVO",
@@ -18838,7 +20004,7 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
18838
20004
  }
18839
20005
  const allowedTypes = /* @__PURE__ */ new Set(["user", "department", "actor"]);
18840
20006
  for (const [index, item] of userScope.entries()) {
18841
- if (!isRecord3(item)) {
20007
+ if (!isRecord4(item)) {
18842
20008
  throwBodyValidationFailure(
18843
20009
  "access-rule user_scope item must be an object",
18844
20010
  requestType,
@@ -18871,14 +20037,14 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
18871
20037
  }
18872
20038
  }
18873
20039
  function normalizeNumericAccessRuleUserScopeIDs(scope, command, body) {
18874
- if (!isAccessRuleCommand(scope, command) || !isRecord3(body)) {
20040
+ if (!isAccessRuleCommand(scope, command) || !isRecord4(body)) {
18875
20041
  return body;
18876
20042
  }
18877
20043
  const normalizeUserScope = (userScope) => {
18878
20044
  if (!Array.isArray(userScope)) return { value: userScope, changed: false };
18879
20045
  let changed = false;
18880
20046
  const value = userScope.map((item) => {
18881
- if (!isRecord3(item) || typeof item.id !== "string" || !/^\d+$/.test(item.id)) {
20047
+ if (!isRecord4(item) || typeof item.id !== "string" || !/^\d+$/.test(item.id)) {
18882
20048
  return item;
18883
20049
  }
18884
20050
  const id = Number(item.id);
@@ -18899,7 +20065,7 @@ function normalizeNumericAccessRuleUserScopeIDs(scope, command, body) {
18899
20065
  if (isAccessRuleBulkApplyCommand(scope, command) && Array.isArray(body.items)) {
18900
20066
  let changed = false;
18901
20067
  const items = body.items.map((item) => {
18902
- if (!isRecord3(item)) return item;
20068
+ if (!isRecord4(item)) return item;
18903
20069
  let nextItem = item;
18904
20070
  for (const key of ["table_id", "rule_id"]) {
18905
20071
  const normalized = normalizeNumericID(nextItem[key]);
@@ -18908,7 +20074,7 @@ function normalizeNumericAccessRuleUserScopeIDs(scope, command, body) {
18908
20074
  changed = true;
18909
20075
  }
18910
20076
  }
18911
- if (isRecord3(nextItem.options)) {
20077
+ if (isRecord4(nextItem.options)) {
18912
20078
  const normalizedUserScope2 = normalizeUserScope(nextItem.options.user_scope);
18913
20079
  if (normalizedUserScope2.changed) {
18914
20080
  nextItem = {
@@ -18925,7 +20091,7 @@ function normalizeNumericAccessRuleUserScopeIDs(scope, command, body) {
18925
20091
  });
18926
20092
  return changed ? { ...body, items } : body;
18927
20093
  }
18928
- if (!isRecord3(body.options)) {
20094
+ if (!isRecord4(body.options)) {
18929
20095
  return body;
18930
20096
  }
18931
20097
  const normalizedUserScope = normalizeUserScope(body.options.user_scope);
@@ -18953,7 +20119,7 @@ function validateAccessRulePolicyShape(scope, command, requestType, policy, env,
18953
20119
  const fields = policy && Array.isArray(policy.fields) ? policy.fields : [];
18954
20120
  const allowedSystemFieldKeys = /* @__PURE__ */ new Set(["created", "updated", "creator"]);
18955
20121
  for (const [index, field] of fields.entries()) {
18956
- if (!isRecord3(field)) continue;
20122
+ if (!isRecord4(field)) continue;
18957
20123
  if (typeof field.key === "number" || typeof field.key === "string" && /^\d+$/.test(field.key)) {
18958
20124
  throwBodyValidationFailure(
18959
20125
  'access-rule policy.fields[].key must be a string prefixed with colon, for example ":1002"; do not use raw numbers',
@@ -18990,8 +20156,26 @@ function requireUpdateContains(scope, command, body, field, env) {
18990
20156
  );
18991
20157
  }
18992
20158
  }
20159
+ function validateChartFieldDimensions(scope, command, requestType, dimensions, pathPrefix, env) {
20160
+ if (!Array.isArray(dimensions)) return;
20161
+ for (const [index, dimension] of dimensions.entries()) {
20162
+ if (!isRecord4(dimension) || typeof dimension.FieldID !== "number") {
20163
+ continue;
20164
+ }
20165
+ if (dimension.IsField !== true) {
20166
+ throwBodyValidationFailure(
20167
+ "widget chart field dimensions require IsField:true when FieldID is present; otherwise grouped statistics collapse into total rows",
20168
+ requestType,
20169
+ `${pathPrefix}.${index}.IsField`,
20170
+ scope,
20171
+ command,
20172
+ env
20173
+ );
20174
+ }
20175
+ }
20176
+ }
18993
20177
  function validateActionSpecificRawBody(scope, command, body, env) {
18994
- if (!isRecord3(body) || !command.requestType) {
20178
+ if (!isRecord4(body) || !command.requestType) {
18995
20179
  return;
18996
20180
  }
18997
20181
  if (isAssignUsersCommand(scope, command)) {
@@ -19008,7 +20192,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19008
20192
  }
19009
20193
  if (isTableSchemaCommand(scope, command)) {
19010
20194
  const fields = Array.isArray(body.fields) ? body.fields : [];
19011
- const hasPermissionPatch = fields.some((field) => isRecord3(field) && ("permission" in field || "permissions" in field || "field_visibility" in field));
20195
+ const hasPermissionPatch = fields.some((field) => isRecord4(field) && ("permission" in field || "permissions" in field || "field_visibility" in field));
19012
20196
  if (hasPermissionPatch) {
19013
20197
  throwBodyValidationFailure(
19014
20198
  "table schema cannot configure per-user permissions. Use access-rule create/update with options.policy.fields for hidden fields",
@@ -19043,7 +20227,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19043
20227
  );
19044
20228
  }
19045
20229
  for (const [index, item] of body.items.entries()) {
19046
- if (!isRecord3(item)) {
20230
+ if (!isRecord4(item)) {
19047
20231
  throwBodyValidationFailure(
19048
20232
  "access-rule bulk-apply body.items[] must be an object",
19049
20233
  command.requestType,
@@ -19053,7 +20237,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19053
20237
  env
19054
20238
  );
19055
20239
  }
19056
- const options2 = isRecord3(item.options) ? item.options : void 0;
20240
+ const options2 = isRecord4(item.options) ? item.options : void 0;
19057
20241
  if (!options2) {
19058
20242
  throwBodyValidationFailure(
19059
20243
  "access-rule bulk-apply body.items[].options is required and must include the full canonical options object",
@@ -19065,7 +20249,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19065
20249
  );
19066
20250
  }
19067
20251
  validateAccessRuleUserScope(scope, command, command.requestType, options2.user_scope, env, `body.items.${index}.options.user_scope`);
19068
- validateAccessRulePolicyShape(scope, command, command.requestType, isRecord3(options2.policy) ? options2.policy : void 0, env, `body.items.${index}.options.policy`);
20252
+ validateAccessRulePolicyShape(scope, command, command.requestType, isRecord4(options2.policy) ? options2.policy : void 0, env, `body.items.${index}.options.policy`);
19069
20253
  }
19070
20254
  return;
19071
20255
  }
@@ -19090,7 +20274,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19090
20274
  env
19091
20275
  );
19092
20276
  }
19093
- const options = isRecord3(body.options) ? body.options : void 0;
20277
+ const options = isRecord4(body.options) ? body.options : void 0;
19094
20278
  if (options && ("permissions" in options || "field_visibility" in options)) {
19095
20279
  throwBodyValidationFailure(
19096
20280
  "access-rule options only supports user_scope, policy, list_options, i18n_name; use options.policy.actions and options.policy.fields",
@@ -19101,7 +20285,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19101
20285
  env
19102
20286
  );
19103
20287
  }
19104
- const policy = options && isRecord3(options.policy) ? options.policy : void 0;
20288
+ const policy = options && isRecord4(options.policy) ? options.policy : void 0;
19105
20289
  if (isAccessRuleUpdateCommand(scope, command) && update.includes("options") && options?.user_scope !== void 0 && !policy) {
19106
20290
  throwBodyValidationFailure(
19107
20291
  'access-rule update with update:["options"] cannot change only options.user_scope because it overwrites policy. Use access-rule assign-users for user assignment, or include the full options.policy and options.list_options.',
@@ -19115,9 +20299,17 @@ function validateActionSpecificRawBody(scope, command, body, env) {
19115
20299
  validateAccessRuleUserScope(scope, command, command.requestType, options?.user_scope, env);
19116
20300
  validateAccessRulePolicyShape(scope, command, command.requestType, policy, env, "body.options.policy");
19117
20301
  }
20302
+ if (isWidgetPreviewDataCommand(scope, command)) {
20303
+ validateChartFieldDimensions(scope, command, command.requestType, body.dimensions, "body.dimensions", env);
20304
+ }
20305
+ if (isWidgetUpdateCommand(scope, command)) {
20306
+ const options = isRecord4(body.options) ? body.options : void 0;
20307
+ const charts = options && isRecord4(options.charts) ? options.charts : void 0;
20308
+ validateChartFieldDimensions(scope, command, command.requestType, charts?.dimensions, "body.options.charts.dimensions", env);
20309
+ }
19118
20310
  }
19119
20311
  function validateActionSpecificBody(scope, command, flags, body, env) {
19120
- if (!isRecord3(body) || !command.requestType) {
20312
+ if (!isRecord4(body) || !command.requestType) {
19121
20313
  return;
19122
20314
  }
19123
20315
  if (scope === "admin" && command.commandPath[0] === "access-rule" && command.commandPath[1] === "update") {
@@ -19127,7 +20319,7 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
19127
20319
  }
19128
20320
  if (isAssignUsersCommand(scope, command)) {
19129
20321
  const update = stringArray(body.update);
19130
- const options = isRecord3(body.options) ? body.options : void 0;
20322
+ const options = isRecord4(body.options) ? body.options : void 0;
19131
20323
  const userScope = options && Array.isArray(options.user_scope) ? options.user_scope : void 0;
19132
20324
  if ("users" in body || "allowedUsers" in body) {
19133
20325
  throwBodyValidationFailure(
@@ -19162,7 +20354,7 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
19162
20354
  validateAccessRuleUserScope(scope, command, command.requestType, userScope, env);
19163
20355
  const assignedUserScope = userScope;
19164
20356
  for (const [index, item] of assignedUserScope.entries()) {
19165
- if (!isRecord3(item)) {
20357
+ if (!isRecord4(item)) {
19166
20358
  throwBodyValidationFailure(
19167
20359
  "access-rule assign-users requires each body.options.user_scope item to be an object",
19168
20360
  command.requestType,
@@ -19187,11 +20379,11 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
19187
20379
  if (command.commandPath[0] === "row" && command.commandPath[1] === "selection-action") {
19188
20380
  const action = flagValue(flags, "action");
19189
20381
  const selection = body.selection;
19190
- if (!isRecord3(selection) || typeof selection.type !== "string") {
20382
+ if (!isRecord4(selection) || typeof selection.type !== "string") {
19191
20383
  return;
19192
20384
  }
19193
20385
  const type = selection.type;
19194
- const condition = isRecord3(selection.condition) ? selection.condition : void 0;
20386
+ const condition = isRecord4(selection.condition) ? selection.condition : void 0;
19195
20387
  const conditionKeys = condition ? Object.keys(condition).filter((key) => key !== "selectAll") : [];
19196
20388
  if (action === "query") {
19197
20389
  if (type === "condition") {
@@ -19228,10 +20420,10 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
19228
20420
  }
19229
20421
  }
19230
20422
  }
19231
- function unwrapData(value) {
20423
+ function unwrapData2(value) {
19232
20424
  let current = value;
19233
20425
  for (let i = 0; i < 3; i += 1) {
19234
- if (isRecord3(current) && isRecord3(current.data)) {
20426
+ if (isRecord4(current) && isRecord4(current.data)) {
19235
20427
  current = current.data;
19236
20428
  continue;
19237
20429
  }
@@ -19240,23 +20432,23 @@ function unwrapData(value) {
19240
20432
  return current;
19241
20433
  }
19242
20434
  function numericFieldKeys(fields) {
19243
- if (!isRecord3(fields)) return [];
20435
+ if (!isRecord4(fields)) return [];
19244
20436
  return Object.keys(fields).filter((key) => /^\d+$/.test(key)).sort((left, right) => Number(left) - Number(right));
19245
20437
  }
19246
20438
  function permitFieldId(permit) {
19247
- if (!isRecord3(permit) || typeof permit.key !== "string") return void 0;
20439
+ if (!isRecord4(permit) || typeof permit.key !== "string") return void 0;
19248
20440
  const match = /^:(\d+)$/.exec(permit.key);
19249
20441
  return match?.[1];
19250
20442
  }
19251
20443
  function rowFieldPermits(value) {
19252
- const data = unwrapData(value);
19253
- const fieldPermits = isRecord3(data) && isRecord3(data.fieldPermits) ? data.fieldPermits : void 0;
19254
- return fieldPermits && Array.isArray(fieldPermits.fields) ? fieldPermits.fields.filter((item) => isRecord3(item)) : [];
20444
+ const data = unwrapData2(value);
20445
+ const fieldPermits = isRecord4(data) && isRecord4(data.fieldPermits) ? data.fieldPermits : void 0;
20446
+ return fieldPermits && Array.isArray(fieldPermits.fields) ? fieldPermits.fields.filter((item) => isRecord4(item)) : [];
19255
20447
  }
19256
20448
  function buildRowValueEvidence(command, responseBody) {
19257
20449
  if (command.scope !== "user" || command.commandPath[0] !== "row") return void 0;
19258
20450
  const action = command.commandPath[1];
19259
- const data = unwrapData(responseBody);
20451
+ const data = unwrapData2(responseBody);
19260
20452
  const rules = [
19261
20453
  "current row values come only from row query fields or row get record.fields",
19262
20454
  "table schema fields[].value and default_value_mode are schema defaults, not returned row values",
@@ -19264,7 +20456,7 @@ function buildRowValueEvidence(command, responseBody) {
19264
20456
  "read visibility status is fieldPermits read:false; FIELD_PERMISSION_REQUIRED is only a write preflight error"
19265
20457
  ];
19266
20458
  if (action === "get") {
19267
- const record2 = isRecord3(data) && isRecord3(data.record) ? data.record : void 0;
20459
+ const record2 = isRecord4(data) && isRecord4(data.record) ? data.record : void 0;
19268
20460
  const returnedFieldIds = numericFieldKeys(record2?.fields);
19269
20461
  const permits = rowFieldPermits(responseBody);
19270
20462
  const permitFieldIds = permits.map(permitFieldId).filter((id) => Boolean(id));
@@ -19280,10 +20472,10 @@ function buildRowValueEvidence(command, responseBody) {
19280
20472
  };
19281
20473
  }
19282
20474
  if (action === "query") {
19283
- const items = isRecord3(data) && Array.isArray(data.items) ? data.items : [];
20475
+ const items = isRecord4(data) && Array.isArray(data.items) ? data.items : [];
19284
20476
  return {
19285
20477
  source: "row query items[].fields",
19286
- rows: items.filter((item) => isRecord3(item)).map((item) => ({
20478
+ rows: items.filter((item) => isRecord4(item)).map((item) => ({
19287
20479
  rowId: item.id,
19288
20480
  returnedFieldIds: numericFieldKeys(item.fields)
19289
20481
  })),
@@ -19317,14 +20509,14 @@ function rowCommandNeedsPolicy(command) {
19317
20509
  return command.scope === "user" && command.commandPath[0] === "row";
19318
20510
  }
19319
20511
  function extractIngressItems(appDetail) {
19320
- const appData = unwrapData(appDetail);
19321
- const ingress = isRecord3(appData) ? appData.ingress : void 0;
19322
- const groups = isRecord3(ingress) && Array.isArray(ingress.groups) ? ingress.groups : [];
20512
+ const appData = unwrapData2(appDetail);
20513
+ const ingress = isRecord4(appData) ? appData.ingress : void 0;
20514
+ const groups = isRecord4(ingress) && Array.isArray(ingress.groups) ? ingress.groups : [];
19323
20515
  const items = [];
19324
20516
  for (const group of groups) {
19325
- const groupItems = isRecord3(group) && Array.isArray(group.items) ? group.items : [];
20517
+ const groupItems = isRecord4(group) && Array.isArray(group.items) ? group.items : [];
19326
20518
  for (const item of groupItems) {
19327
- if (!isRecord3(item)) continue;
20519
+ if (!isRecord4(item)) continue;
19328
20520
  const id = typeof item.id === "string" ? item.id : typeof item.ID === "string" ? item.ID : "";
19329
20521
  if (id) {
19330
20522
  items.push({ id });
@@ -19334,29 +20526,29 @@ function extractIngressItems(appDetail) {
19334
20526
  return items;
19335
20527
  }
19336
20528
  function ingressMatchesTableAndAction(ingressDetail, tableId, action) {
19337
- const ingressData = unwrapData(ingressDetail);
19338
- if (!isRecord3(ingressData)) return void 0;
20529
+ const ingressData = unwrapData2(ingressDetail);
20530
+ if (!isRecord4(ingressData)) return void 0;
19339
20531
  const id = typeof ingressData.id === "number" || typeof ingressData.id === "string" ? ingressData.id : typeof ingressData.ID === "number" || typeof ingressData.ID === "string" ? ingressData.ID : void 0;
19340
20532
  if (String(id ?? "") !== tableId) return void 0;
19341
20533
  const policyID = typeof ingressData.hash_id === "string" ? ingressData.hash_id : typeof ingressData.hashId === "string" ? ingressData.hashId : void 0;
19342
- const policy = isRecord3(ingressData.policy) ? ingressData.policy : void 0;
20534
+ const policy = isRecord4(ingressData.policy) ? ingressData.policy : void 0;
19343
20535
  if (!action) return { policyID: policyID || "", policy };
19344
20536
  const actions = policy && Array.isArray(policy.actions) ? policy.actions.filter((item) => typeof item === "string") : [];
19345
20537
  if (!actions.includes(action)) return void 0;
19346
20538
  return { policyID: policyID || "", policy };
19347
20539
  }
19348
20540
  function writtenRowFieldIds(command, body) {
19349
- if (!isRecord3(body)) return [];
20541
+ if (!isRecord4(body)) return [];
19350
20542
  const source = command.commandPath[1] === "create" ? body.fields : command.commandPath[1] === "update" ? body.data : void 0;
19351
- if (!isRecord3(source)) return [];
20543
+ if (!isRecord4(source)) return [];
19352
20544
  return Object.keys(source).filter((key) => /^\d+$/.test(key)).map((key) => Number(key));
19353
20545
  }
19354
20546
  function fieldWriteAllowedByPolicy(policy, fieldId) {
19355
20547
  if (!policy) return true;
19356
20548
  const fields = Array.isArray(policy.fields) ? policy.fields : [];
19357
- const explicit = fields.find((item) => isRecord3(item) && item.key === `:${fieldId}`);
19358
- if (isRecord3(explicit) && explicit.write === false) return false;
19359
- if (isRecord3(explicit) && explicit.write === true) return true;
20549
+ const explicit = fields.find((item) => isRecord4(item) && item.key === `:${fieldId}`);
20550
+ if (isRecord4(explicit) && explicit.write === false) return false;
20551
+ if (isRecord4(explicit) && explicit.write === true) return true;
19360
20552
  if (policy.all_fields_write === false) return false;
19361
20553
  return true;
19362
20554
  }
@@ -19427,7 +20619,7 @@ async function injectResolvedPolicyID(command, runtimeEnv, flags, query, body, f
19427
20619
  if (typeof query.policy_id === "string" && query.policy_id) {
19428
20620
  return { query, body };
19429
20621
  }
19430
- if (isRecord3(body) && typeof body.policy_id === "string" && body.policy_id) {
20622
+ if (isRecord4(body) && typeof body.policy_id === "string" && body.policy_id) {
19431
20623
  return { query, body };
19432
20624
  }
19433
20625
  const resolvedPolicy = await resolvePolicyIDForRowCommand(command, runtimeEnv, flags, fetchImpl);
@@ -19436,7 +20628,7 @@ async function injectResolvedPolicyID(command, runtimeEnv, flags, query, body, f
19436
20628
  if (command.commandPath[1] === "get") {
19437
20629
  return { query: { ...query, policy_id: policyID }, body };
19438
20630
  }
19439
- if (isRecord3(body)) {
20631
+ if (isRecord4(body)) {
19440
20632
  return { query, body: { ...body, policy_id: policyID } };
19441
20633
  }
19442
20634
  return { query, body };
@@ -19445,7 +20637,7 @@ function assertNoUserPolicyIDInput(command, runtimeEnv, query, body) {
19445
20637
  if (!rowCommandNeedsPolicy(command)) {
19446
20638
  return;
19447
20639
  }
19448
- if ("policy_id" in query || isRecord3(body) && "policy_id" in body) {
20640
+ if ("policy_id" in query || isRecord4(body) && "policy_id" in body) {
19449
20641
  throw new CLIError("INTERNAL_POLICY_ID_NOT_ALLOWED", "policy_id is an internal Arcubase ingress parameter; use app/table/row ids only", 2, {
19450
20642
  operation: `user.${command.module}.${command.functionName}`,
19451
20643
  issues: [{ path: "policy_id", message: "do not provide policy_id in flags, query file, or body JSON" }],
@@ -19482,6 +20674,151 @@ async function requestJSON(runtimeEnv, method, endpoint, body, fetchImpl) {
19482
20674
  }
19483
20675
  return { status: response.status, data: parsedResponse };
19484
20676
  }
20677
+ function unwrapResponseData(payload) {
20678
+ return isRecord4(payload) && "data" in payload ? payload.data : payload;
20679
+ }
20680
+ function extractSDKGenAppPayload(payload) {
20681
+ const appPayload = unwrapResponseData(payload);
20682
+ if (!isRecord4(appPayload)) {
20683
+ throw new CLIError("SDK_GEN_INVALID_SCHEMA", "sdk-gen expected app detail response data", 2);
20684
+ }
20685
+ return appPayload;
20686
+ }
20687
+ function extractSDKGenEntityRefs(appPayload) {
20688
+ const sourceEntities = Array.isArray(appPayload.entities) ? appPayload.entities : Array.isArray(appPayload.tables) ? appPayload.tables : Array.isArray(appPayload.entitys) ? appPayload.entitys : [];
20689
+ const refs = sourceEntities.filter((item) => isRecord4(item)).map((item) => item.id).filter((id) => typeof id === "string" || typeof id === "number").map((id) => ({ id: String(id) }));
20690
+ return refs;
20691
+ }
20692
+ function resolveSDKGenAppId(flagAppId, appPayload) {
20693
+ const fromPayload = typeof appPayload.id === "number" ? appPayload.id : typeof appPayload.app_id === "number" ? appPayload.app_id : void 0;
20694
+ const fromFlag = Number(flagAppId);
20695
+ if (Number.isFinite(fromFlag)) return fromFlag;
20696
+ if (fromPayload) return fromPayload;
20697
+ throw new CLIError("SDK_GEN_APP_ID_REQUIRED", "sdk-gen expected numeric app id", 2);
20698
+ }
20699
+ function walkSDKGenFields(fields, visit) {
20700
+ if (!Array.isArray(fields)) {
20701
+ return;
20702
+ }
20703
+ for (const field of fields) {
20704
+ if (!isRecord4(field)) {
20705
+ continue;
20706
+ }
20707
+ visit(field);
20708
+ walkSDKGenFields(field.children, visit);
20709
+ }
20710
+ }
20711
+ function collectExistingSDKGenFieldKeys(entity) {
20712
+ const keys = /* @__PURE__ */ new Set();
20713
+ walkSDKGenFields(entity.fields, (field) => {
20714
+ if (typeof field.key === "string" && field.key.trim() !== "") {
20715
+ keys.add(field.key.trim());
20716
+ }
20717
+ });
20718
+ return keys;
20719
+ }
20720
+ function nextSDKGenFallbackFieldKey(fieldId, usedKeys) {
20721
+ const base = `field${fieldId}`;
20722
+ if (!usedKeys.has(base)) {
20723
+ usedKeys.add(base);
20724
+ return base;
20725
+ }
20726
+ let index = 2;
20727
+ while (usedKeys.has(`${base}_${index}`)) {
20728
+ index++;
20729
+ }
20730
+ const key = `${base}_${index}`;
20731
+ usedKeys.add(key);
20732
+ return key;
20733
+ }
20734
+ function initializeMissingSDKGenFieldKeys(entity) {
20735
+ const usedKeys = collectExistingSDKGenFieldKeys(entity);
20736
+ const updates = [];
20737
+ walkSDKGenFields(entity.fields, (field) => {
20738
+ if (typeof field.id !== "number") {
20739
+ return;
20740
+ }
20741
+ if (typeof field.key === "string" && field.key.trim() !== "") {
20742
+ field.key = field.key.trim();
20743
+ return;
20744
+ }
20745
+ const key = nextSDKGenFallbackFieldKey(field.id, usedKeys);
20746
+ field.key = key;
20747
+ updates.push({ id: field.id, key });
20748
+ });
20749
+ return updates;
20750
+ }
20751
+ async function executeDevSDKGen(runtimeEnv, flags, fetchImpl) {
20752
+ validateDevSDKGenFlags(flags);
20753
+ const appId = flagValue(flags, "app-id");
20754
+ const outDir = flagValue(flags, "out");
20755
+ if (!appId) {
20756
+ throw new CLIError("MISSING_PATH_FLAG", "missing required flag --app-id", 2);
20757
+ }
20758
+ if (!outDir) {
20759
+ throw new CLIError("MISSING_FLAG", "missing required flag --out", 2, {
20760
+ operation: "dev sdk-gen",
20761
+ hint: "retry with --out src/arcubase"
20762
+ });
20763
+ }
20764
+ const endpoint = `/api/apps/${encodeURIComponent(appId)}`;
20765
+ const appDetail = await requestJSON(runtimeEnv, "GET", endpoint, void 0, fetchImpl);
20766
+ const appPayload = extractSDKGenAppPayload(appDetail.data);
20767
+ let entityRefs = extractSDKGenEntityRefs(appPayload);
20768
+ if (entityRefs.length === 0) {
20769
+ const entitiesEndpoint = `/api/apps/${encodeURIComponent(appId)}/entities`;
20770
+ const entityList = await requestJSON(runtimeEnv, "GET", entitiesEndpoint, void 0, fetchImpl);
20771
+ const entityListPayload = unwrapResponseData(entityList.data);
20772
+ entityRefs = extractSDKGenEntityRefs({ entities: entityListPayload });
20773
+ }
20774
+ if (entityRefs.length === 0) {
20775
+ throw new CLIError("SDK_GEN_NO_ENTITIES", "sdk-gen could not find entities in app detail response", 2);
20776
+ }
20777
+ const entities = [];
20778
+ const initializedFieldKeys = [];
20779
+ for (const entityRef of entityRefs) {
20780
+ const entityEndpoint = `/api/apps/${encodeURIComponent(appId)}/entity/${encodeURIComponent(entityRef.id)}`;
20781
+ const entityDetail = await requestJSON(runtimeEnv, "GET", entityEndpoint, void 0, fetchImpl);
20782
+ const entityPayload = unwrapResponseData(entityDetail.data);
20783
+ if (!isRecord4(entityPayload)) {
20784
+ throw new CLIError("SDK_GEN_INVALID_SCHEMA", "sdk-gen expected entity detail response data", 2);
20785
+ }
20786
+ const customKeyUpdates = initializeMissingSDKGenFieldKeys(entityPayload);
20787
+ if (customKeyUpdates.length > 0) {
20788
+ const customKeysEndpoint = `/api/apps/${encodeURIComponent(appId)}/entity/${encodeURIComponent(entityRef.id)}/custom-keys`;
20789
+ await requestJSON(runtimeEnv, "PUT", customKeysEndpoint, customKeyUpdates, fetchImpl);
20790
+ initializedFieldKeys.push({
20791
+ entityId: typeof entityPayload.id === "number" ? entityPayload.id : Number(entityRef.id),
20792
+ fields: customKeyUpdates.map((item) => item.key)
20793
+ });
20794
+ }
20795
+ entities.push(entityPayload);
20796
+ }
20797
+ const generated = generateArcubaseProjectSDK({
20798
+ id: resolveSDKGenAppId(appId, appPayload),
20799
+ name: typeof appPayload.name === "string" ? appPayload.name : void 0,
20800
+ entities
20801
+ });
20802
+ const absoluteOutDir = path2.resolve(process.cwd(), outDir);
20803
+ for (const file2 of generated.files) {
20804
+ const targetPath = path2.resolve(absoluteOutDir, file2.path);
20805
+ if (!targetPath.startsWith(`${absoluteOutDir}${path2.sep}`)) {
20806
+ throw new CLIError("SDK_GEN_INVALID_OUTPUT_PATH", `invalid generated file path: ${file2.path}`, 2);
20807
+ }
20808
+ fs3.mkdirSync(path2.dirname(targetPath), { recursive: true });
20809
+ fs3.writeFileSync(targetPath, file2.contents);
20810
+ }
20811
+ return {
20812
+ kind: "result",
20813
+ commandPath: ["dev", "sdk-gen"],
20814
+ status: appDetail.status,
20815
+ data: {
20816
+ out: absoluteOutDir,
20817
+ files: generated.files.map((file2) => file2.path),
20818
+ initializedFieldKeys
20819
+ }
20820
+ };
20821
+ }
19485
20822
  function requiredStringFlag(flags, flag) {
19486
20823
  const value = flagValue(flags, flag);
19487
20824
  if (!value) {
@@ -19547,10 +20884,10 @@ async function executeWatchAppBundleImportTask(runtimeEnv, flags, fetchImpl) {
19547
20884
  while (Date.now() <= deadline) {
19548
20885
  const result = await requestJSON(runtimeEnv, "GET", endpoint, void 0, fetchImpl);
19549
20886
  latest = result.data;
19550
- const payload = isRecord3(latest) && isRecord3(latest.data) ? latest.data : latest;
19551
- const status = isRecord3(payload) ? payload.status : void 0;
20887
+ const payload = isRecord4(latest) && isRecord4(latest.data) ? latest.data : latest;
20888
+ const status = isRecord4(payload) ? payload.status : void 0;
19552
20889
  if (status === "finished") {
19553
- const appID = isRecord3(payload) ? Number(payload.app_id) : 0;
20890
+ const appID = isRecord4(payload) ? Number(payload.app_id) : 0;
19554
20891
  if (!Number.isFinite(appID) || appID <= 0) {
19555
20892
  throw new CLIError("IMPORT_TASK_APP_ID_MISSING", "app bundle import task finished without app_id", 1, {
19556
20893
  endpoint,
@@ -19566,7 +20903,7 @@ async function executeWatchAppBundleImportTask(runtimeEnv, flags, fetchImpl) {
19566
20903
  };
19567
20904
  }
19568
20905
  if (status === "failed") {
19569
- throw new CLIError("IMPORT_TASK_FAILED", isRecord3(payload) && typeof payload.error === "string" ? payload.error : "app bundle import task failed", 1, {
20906
+ throw new CLIError("IMPORT_TASK_FAILED", isRecord4(payload) && typeof payload.error === "string" ? payload.error : "app bundle import task failed", 1, {
19570
20907
  endpoint,
19571
20908
  responseBody: stringifyUpstreamBody(latest)
19572
20909
  });
@@ -19635,25 +20972,25 @@ async function postEntityImportAction(runtimeEnv, appId, entityId, body, fetchIm
19635
20972
  function extractImportTaskID(value) {
19636
20973
  const candidates = [
19637
20974
  value,
19638
- isRecord3(value) ? value.data : void 0
20975
+ isRecord4(value) ? value.data : void 0
19639
20976
  ];
19640
20977
  for (const candidate of candidates) {
19641
- if (isRecord3(candidate) && typeof candidate.taskId === "string") return candidate.taskId;
19642
- if (isRecord3(candidate) && typeof candidate.task_id === "string") return candidate.task_id;
20978
+ if (isRecord4(candidate) && typeof candidate.taskId === "string") return candidate.taskId;
20979
+ if (isRecord4(candidate) && typeof candidate.task_id === "string") return candidate.task_id;
19643
20980
  if (typeof candidate === "string") return candidate;
19644
20981
  }
19645
20982
  throw new CLIError("UPSTREAM_RESPONSE_INVALID", "import response did not include taskId", 1);
19646
20983
  }
19647
20984
  function extractUploadToken(value) {
19648
- const payload = isRecord3(value) && isRecord3(value.data) ? value.data : value;
19649
- if (isRecord3(payload) && isRecord3(payload.token)) return payload.token;
20985
+ const payload = isRecord4(value) && isRecord4(value.data) ? value.data : value;
20986
+ if (isRecord4(payload) && isRecord4(payload.token)) return payload.token;
19650
20987
  throw new CLIError("UPSTREAM_RESPONSE_INVALID", "import init-token response did not include upload token", 1);
19651
20988
  }
19652
20989
  function compileEntityImportConfig(format, mapping, filePath) {
19653
20990
  if (format === "excel") {
19654
20991
  return compileExcelImportMapping(mapping);
19655
20992
  }
19656
- const delimiter = isRecord3(mapping) && typeof mapping.delimiter === "string" ? mapping.delimiter : ",";
20993
+ const delimiter = isRecord4(mapping) && typeof mapping.delimiter === "string" ? mapping.delimiter : ",";
19657
20994
  return compileCSVImportMapping(mapping, csvHeadersFromLocalFile(filePath, delimiter));
19658
20995
  }
19659
20996
  async function executeEntityRecordImport(command, runtimeEnv, flags, fetchImpl) {
@@ -19680,8 +21017,8 @@ async function executeEntityRecordImport(command, runtimeEnv, flags, fetchImpl)
19680
21017
  let latest = null;
19681
21018
  while (Date.now() <= deadline) {
19682
21019
  latest = await postEntityImportAction(runtimeEnv, appId, entityId, { _import_action: "get-state", task_id: taskId }, fetchImpl);
19683
- const payload = isRecord3(latest) && isRecord3(latest.data) ? latest.data : latest;
19684
- const status = isRecord3(payload) ? payload.status : void 0;
21020
+ const payload = isRecord4(latest) && isRecord4(latest.data) ? latest.data : latest;
21021
+ const status = isRecord4(payload) ? payload.status : void 0;
19685
21022
  if (status === "finished") {
19686
21023
  return {
19687
21024
  kind: "result",
@@ -19704,11 +21041,11 @@ async function executeEntityRecordImport(command, runtimeEnv, flags, fetchImpl)
19704
21041
  function extractCreatedTableID(value) {
19705
21042
  const candidates = [
19706
21043
  value,
19707
- isRecord3(value) ? value.data : void 0,
19708
- isRecord3(value) && isRecord3(value.data) ? value.data.data : void 0
21044
+ isRecord4(value) ? value.data : void 0,
21045
+ isRecord4(value) && isRecord4(value.data) ? value.data.data : void 0
19709
21046
  ];
19710
21047
  for (const candidate of candidates) {
19711
- if (isRecord3(candidate) && typeof candidate.id === "number") {
21048
+ if (isRecord4(candidate) && typeof candidate.id === "number") {
19712
21049
  return candidate.id;
19713
21050
  }
19714
21051
  }
@@ -19722,7 +21059,7 @@ function normalizeTableCreateSchemaBody(body, appId, tableId) {
19722
21059
  app_id: Number.isFinite(Number(appId)) ? Number(appId) : body.app_id,
19723
21060
  schema_version: typeof body.schema_version === "number" ? body.schema_version : 0,
19724
21061
  layout: Array.isArray(body.layout) ? body.layout : [],
19725
- options: isRecord3(body.options) ? body.options : { Buttons: [], CustomActions: [], FrontendEvents: [], TitleFormat: { Fields: [], Parts: [], Body: "" }, misc: {} },
21062
+ options: isRecord4(body.options) ? body.options : { Buttons: [], CustomActions: [], FrontendEvents: [], TitleFormat: { Fields: [], Parts: [], Body: "" }, misc: {} },
19726
21063
  workflow_enabled: typeof body.workflow_enabled === "boolean" ? body.workflow_enabled : false
19727
21064
  };
19728
21065
  }
@@ -19731,7 +21068,7 @@ async function executeTableCreateWithSchema(command, runtimeEnv, flags, body, fe
19731
21068
  if (!appId) {
19732
21069
  throw new CLIError("MISSING_PATH_FLAG", "missing required flag --app-id", 2);
19733
21070
  }
19734
- if (!isRecord3(body)) {
21071
+ if (!isRecord4(body)) {
19735
21072
  throw new CLIError("BODY_VALIDATION_FAILED", "table create body must be an object", 2);
19736
21073
  }
19737
21074
  const createBody = {
@@ -19801,6 +21138,16 @@ async function executeCLI(scope, argv, env, fetchImpl = fetch) {
19801
21138
  }
19802
21139
  return { kind: "help", text: renderRootHelp(scope) };
19803
21140
  }
21141
+ if (isDevSDKGenCommand(scope, moduleName, commandName)) {
21142
+ if (hasFlag(parsed.flags, "help")) {
21143
+ return { kind: "help", text: renderDevSDKGenHelp() };
21144
+ }
21145
+ const runtimeEnv2 = env ?? loadRuntimeEnv(scope);
21146
+ return executeDevSDKGen(runtimeEnv2, parsed.flags, fetchImpl);
21147
+ }
21148
+ if (scope === "admin" && moduleName === "dev" && !commandName) {
21149
+ return { kind: "help", text: renderDevModuleHelp() };
21150
+ }
19804
21151
  const singleTokenCommand = !commandName ? findCommand(scope, moduleName) : null;
19805
21152
  if (!commandName && !singleTokenCommand) {
19806
21153
  if (hasFlag(parsed.flags, "help-examples")) {
@@ -19863,7 +21210,7 @@ async function executeCLI(scope, argv, env, fetchImpl = fetch) {
19863
21210
  if (isTableCreateCommand(scope, command)) {
19864
21211
  requireTableCreateSchemaBody(scope, command, body, runtimeEnv);
19865
21212
  validateActionSpecificRawBody(scope, command, body, runtimeEnv);
19866
- const { parent: _parent, ...schemaBody } = isRecord3(body) ? body : {};
21213
+ const { parent: _parent, ...schemaBody } = isRecord4(body) ? body : {};
19867
21214
  const parsedBody = getBodySchema("EntitySaveReqVO")?.safeParse(schemaBody);
19868
21215
  if (!parsedBody?.success) {
19869
21216
  const message = parsedBody ? parsedBody.error.issues.map((issue2) => `${issue2.path.join(".")}: ${issue2.message}`).join("; ") : "EntitySaveReqVO schema is not available";