@carthooks/arcubase-cli 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/bundle/arcubase-admin.mjs +907 -10
  2. package/bundle/arcubase.mjs +907 -10
  3. package/dist/runtime/command_registry.d.ts +8 -0
  4. package/dist/runtime/command_registry.d.ts.map +1 -1
  5. package/dist/runtime/command_registry.js +35 -0
  6. package/dist/runtime/entity_save_schema.d.ts +15 -0
  7. package/dist/runtime/entity_save_schema.d.ts.map +1 -0
  8. package/dist/runtime/entity_save_schema.js +641 -0
  9. package/dist/runtime/errors.d.ts +10 -0
  10. package/dist/runtime/errors.d.ts.map +1 -1
  11. package/dist/runtime/execute.d.ts.map +1 -1
  12. package/dist/runtime/execute.js +89 -10
  13. package/dist/runtime/zod_registry.d.ts +6 -0
  14. package/dist/runtime/zod_registry.d.ts.map +1 -1
  15. package/dist/runtime/zod_registry.js +133 -0
  16. package/dist/tests/command_registry.test.js +5 -0
  17. package/dist/tests/entity_save_schema.test.d.ts +2 -0
  18. package/dist/tests/entity_save_schema.test.d.ts.map +1 -0
  19. package/dist/tests/entity_save_schema.test.js +221 -0
  20. package/dist/tests/execute_validation.test.js +450 -0
  21. package/dist/tests/help.test.js +33 -0
  22. package/package.json +1 -1
  23. package/sdk-dist/docs/runtime-reference/README.md +177 -0
  24. package/sdk-dist/docs/runtime-reference/entity-schema/README.md +120 -0
  25. package/sdk-dist/docs/runtime-reference/entity-schema/address.md +34 -0
  26. package/sdk-dist/docs/runtime-reference/entity-schema/boolean.md +37 -0
  27. package/sdk-dist/docs/runtime-reference/entity-schema/button.md +47 -0
  28. package/sdk-dist/docs/runtime-reference/entity-schema/checkbox.md +61 -0
  29. package/sdk-dist/docs/runtime-reference/entity-schema/datasets.md +35 -0
  30. package/sdk-dist/docs/runtime-reference/entity-schema/datetime.md +40 -0
  31. package/sdk-dist/docs/runtime-reference/entity-schema/department.md +33 -0
  32. package/sdk-dist/docs/runtime-reference/entity-schema/departments.md +34 -0
  33. package/sdk-dist/docs/runtime-reference/entity-schema/divider.md +39 -0
  34. package/sdk-dist/docs/runtime-reference/entity-schema/file.md +44 -0
  35. package/sdk-dist/docs/runtime-reference/entity-schema/formula.md +44 -0
  36. package/sdk-dist/docs/runtime-reference/entity-schema/image.md +43 -0
  37. package/sdk-dist/docs/runtime-reference/entity-schema/linkto.md +67 -0
  38. package/sdk-dist/docs/runtime-reference/entity-schema/location.md +32 -0
  39. package/sdk-dist/docs/runtime-reference/entity-schema/lookup.md +41 -0
  40. package/sdk-dist/docs/runtime-reference/entity-schema/member.md +37 -0
  41. package/sdk-dist/docs/runtime-reference/entity-schema/members.md +31 -0
  42. package/sdk-dist/docs/runtime-reference/entity-schema/number.md +70 -0
  43. package/sdk-dist/docs/runtime-reference/entity-schema/query.md +50 -0
  44. package/sdk-dist/docs/runtime-reference/entity-schema/radio.md +53 -0
  45. package/sdk-dist/docs/runtime-reference/entity-schema/relation.md +55 -0
  46. package/sdk-dist/docs/runtime-reference/entity-schema/relationfield.md +38 -0
  47. package/sdk-dist/docs/runtime-reference/entity-schema/rollup.md +54 -0
  48. package/sdk-dist/docs/runtime-reference/entity-schema/select.md +63 -0
  49. package/sdk-dist/docs/runtime-reference/entity-schema/selects.md +51 -0
  50. package/sdk-dist/docs/runtime-reference/entity-schema/serialnumber.md +48 -0
  51. package/sdk-dist/docs/runtime-reference/entity-schema/signature.md +31 -0
  52. package/sdk-dist/docs/runtime-reference/entity-schema/status.md +70 -0
  53. package/sdk-dist/docs/runtime-reference/entity-schema/subform.md +74 -0
  54. package/sdk-dist/docs/runtime-reference/entity-schema/tags.md +19 -0
  55. package/sdk-dist/docs/runtime-reference/entity-schema/text.md +76 -0
  56. package/sdk-dist/docs/runtime-reference/entity-schema/textarea.md +47 -0
  57. package/sdk-dist/docs/runtime-reference/entity-schema/workflow_status.md +17 -0
  58. package/sdk-dist/docs/runtime-reference/entity-schema.md +197 -0
  59. package/sdk-dist/docs/runtime-reference/examples/README.md +51 -0
  60. package/sdk-dist/docs/runtime-reference/examples/crm-01/README.md +20 -0
  61. package/sdk-dist/docs/runtime-reference/examples/mes-01/README.md +21 -0
  62. package/sdk-dist/docs/runtime-reference/examples/oms-01/README.md +164 -0
  63. package/sdk-dist/docs/runtime-reference/examples/oms-01/app-overview.md +79 -0
  64. package/sdk-dist/docs/runtime-reference/examples/oms-01/create-app.json +3 -0
  65. package/sdk-dist/docs/runtime-reference/examples/oms-01/goods-receipt.create-entity.json +3 -0
  66. package/sdk-dist/docs/runtime-reference/examples/oms-01/goods-receipt.schema.json +159 -0
  67. package/sdk-dist/docs/runtime-reference/examples/oms-01/item-master.create-entity.json +3 -0
  68. package/sdk-dist/docs/runtime-reference/examples/oms-01/item-master.schema.json +179 -0
  69. package/sdk-dist/docs/runtime-reference/examples/oms-01/picking-list.create-entity.json +3 -0
  70. package/sdk-dist/docs/runtime-reference/examples/oms-01/picking-list.schema.json +168 -0
  71. package/sdk-dist/docs/runtime-reference/examples/oms-01/purchase-order.create-entity.json +3 -0
  72. package/sdk-dist/docs/runtime-reference/examples/oms-01/purchase-order.schema.json +417 -0
  73. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.bulk-update.json +22 -0
  74. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.create-entity.json +3 -0
  75. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.query.json +10 -0
  76. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.row.insert.json +28 -0
  77. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.schema.json +398 -0
  78. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.selection.condition.json +13 -0
  79. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.selection.ids.json +7 -0
  80. package/sdk-dist/docs/runtime-reference/examples/oms-01/stock-issue.create-entity.json +3 -0
  81. package/sdk-dist/docs/runtime-reference/examples/oms-01/stock-issue.schema.json +137 -0
  82. package/sdk-dist/docs/runtime-reference/examples/wms-01/README.md +21 -0
  83. package/sdk-dist/docs/runtime-reference/row-crud.md +186 -0
  84. package/sdk-dist/docs/runtime-reference/search-and-bulk-actions.md +494 -0
  85. package/sdk-dist/docs/runtime-reference/table-lifecycle.md +123 -0
  86. package/sdk-dist/docs/runtime-reference/workflow/README.md +19 -0
  87. package/src/runtime/command_registry.ts +47 -0
  88. package/src/runtime/entity_save_schema.ts +708 -0
  89. package/src/runtime/errors.ts +11 -0
  90. package/src/runtime/execute.ts +123 -10
  91. package/src/runtime/zod_registry.ts +154 -0
  92. package/src/tests/command_registry.test.ts +6 -0
  93. package/src/tests/entity_save_schema.test.ts +236 -0
  94. package/src/tests/execute_validation.test.ts +598 -0
  95. package/src/tests/help.test.ts +39 -0
@@ -4738,6 +4738,41 @@ function listModules(scope) {
4738
4738
  function listModuleCommands(scope, moduleName) {
4739
4739
  return listCommands(scope).filter((item) => item.commandPath[0] === moduleName);
4740
4740
  }
4741
+ function levenshtein(a, b) {
4742
+ const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
4743
+ for (let i = 0; i <= a.length; i += 1) dp[i][0] = i;
4744
+ for (let j = 0; j <= b.length; j += 1) dp[0][j] = j;
4745
+ for (let i = 1; i <= a.length; i += 1) {
4746
+ for (let j = 1; j <= b.length; j += 1) {
4747
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
4748
+ dp[i][j] = Math.min(
4749
+ dp[i - 1][j] + 1,
4750
+ dp[i][j - 1] + 1,
4751
+ dp[i - 1][j - 1] + cost
4752
+ );
4753
+ }
4754
+ }
4755
+ return dp[a.length][b.length];
4756
+ }
4757
+ function findCommandSuggestions(moduleName, commandName, limit = 3) {
4758
+ const suggestions = [];
4759
+ for (const scope of ["admin", "user"]) {
4760
+ for (const command of listCommands(scope)) {
4761
+ const [candidateModule, candidateCommand] = command.commandPath;
4762
+ const moduleScore = candidateModule === moduleName ? 0 : levenshtein(candidateModule, moduleName || "");
4763
+ const commandScore = candidateCommand === commandName ? 0 : levenshtein(candidateCommand, commandName || "");
4764
+ const score = commandScore * 3 + moduleScore;
4765
+ suggestions.push({
4766
+ scope,
4767
+ moduleName: candidateModule,
4768
+ commandName: candidateCommand,
4769
+ binary: scope === "admin" ? "arcubase-admin" : "arcubase",
4770
+ score
4771
+ });
4772
+ }
4773
+ }
4774
+ return suggestions.sort((a, b) => a.score - b.score || a.binary.localeCompare(b.binary) || a.moduleName.localeCompare(b.moduleName) || a.commandName.localeCompare(b.commandName)).slice(0, limit);
4775
+ }
4741
4776
 
4742
4777
  // src/runtime/body_loader.ts
4743
4778
  import fs from "fs";
@@ -9661,10 +9696,671 @@ var typeIndex = {
9661
9696
  }
9662
9697
  };
9663
9698
 
9699
+ // src/runtime/entity_save_schema.ts
9700
+ var simpleFieldTypes = [
9701
+ "text",
9702
+ "textarea",
9703
+ "number",
9704
+ "datetime",
9705
+ "boolean",
9706
+ "button",
9707
+ "address",
9708
+ "datasets",
9709
+ "department",
9710
+ "departments",
9711
+ "divider",
9712
+ "file",
9713
+ "image",
9714
+ "location",
9715
+ "member",
9716
+ "members",
9717
+ "signature",
9718
+ "tags",
9719
+ "workflow_status",
9720
+ "mobile"
9721
+ ];
9722
+ var enumFieldTypes = ["select", "selects", "radio", "checkbox", "status"];
9723
+ var relationFieldTypes = ["linkto", "relation", "query"];
9724
+ var strictFieldTypes = /* @__PURE__ */ new Set([
9725
+ ...simpleFieldTypes,
9726
+ ...enumFieldTypes,
9727
+ ...relationFieldTypes,
9728
+ "formula",
9729
+ "lookup",
9730
+ "relationfield",
9731
+ "rollup",
9732
+ "serialnumber",
9733
+ "subform"
9734
+ ]);
9735
+ var relationTypeSchema = external_exports.union([external_exports.literal("entity"), external_exports.literal("aggregation")]);
9736
+ var linkModeSchema = external_exports.union([external_exports.literal("manual"), external_exports.literal("auto")]);
9737
+ var linkStructureSchema = external_exports.union([external_exports.literal("single"), external_exports.literal("multiple")]);
9738
+ var enumItemSchema = external_exports.object({
9739
+ key: external_exports.union([external_exports.number(), external_exports.string()]).optional(),
9740
+ value: external_exports.string().min(1)
9741
+ }).passthrough();
9742
+ var statusItemSchema = external_exports.object({
9743
+ key: external_exports.union([external_exports.number(), external_exports.string()]).optional(),
9744
+ code: external_exports.union([external_exports.number(), external_exports.string()]),
9745
+ value: external_exports.string().min(1)
9746
+ }).passthrough();
9747
+ var sortConfigSchema = external_exports.object({
9748
+ column: external_exports.string().min(1),
9749
+ order: external_exports.union([external_exports.literal("asc"), external_exports.literal("desc")])
9750
+ }).strict();
9751
+ var relationOptionsSchema = external_exports.object({
9752
+ entity_id: external_exports.number().int().positive(),
9753
+ app_id: external_exports.number().int().positive(),
9754
+ type: relationTypeSchema,
9755
+ show_fields: external_exports.array(external_exports.number().int().positive()).optional(),
9756
+ condition: external_exports.record(external_exports.string(), external_exports.any()).optional(),
9757
+ sorts: external_exports.array(sortConfigSchema).optional(),
9758
+ queryFields: external_exports.array(external_exports.number().int().positive()).optional(),
9759
+ subform_id: external_exports.number().int().positive().optional()
9760
+ }).strict();
9761
+ var lookupRelationSchema = external_exports.object({
9762
+ local_linkto_field_id: external_exports.number().int().min(1001),
9763
+ target_field_id: external_exports.number().int().min(1001),
9764
+ target_field_type: external_exports.string().min(1)
9765
+ }).strict();
9766
+ var relationFieldRelationSchema = external_exports.object({
9767
+ app_id: external_exports.number().int().positive(),
9768
+ entity_id: external_exports.number().int().positive(),
9769
+ type: relationTypeSchema.optional(),
9770
+ show_fields: external_exports.array(external_exports.number().int().positive()).optional(),
9771
+ condition: external_exports.record(external_exports.string(), external_exports.any()).optional(),
9772
+ sorts: external_exports.array(sortConfigSchema).optional(),
9773
+ queryFields: external_exports.array(external_exports.number().int().positive()).optional(),
9774
+ subform_id: external_exports.number().int().positive().optional()
9775
+ }).strict();
9776
+ var formulaSchema = external_exports.object({
9777
+ code: external_exports.string().min(1),
9778
+ jsonlogic: external_exports.record(external_exports.string(), external_exports.any())
9779
+ }).strict();
9780
+ var serialPartBuildinStringSchema = external_exports.object({
9781
+ mode: external_exports.literal("buildin"),
9782
+ type: external_exports.literal("string"),
9783
+ options: external_exports.object({
9784
+ value: external_exports.string()
9785
+ }).strict()
9786
+ }).strict();
9787
+ var serialPartBuildinDateSchema = external_exports.object({
9788
+ mode: external_exports.literal("buildin"),
9789
+ type: external_exports.literal("date"),
9790
+ options: external_exports.object({
9791
+ format: external_exports.string().optional(),
9792
+ perdefined: external_exports.boolean().optional(),
9793
+ perdefinedFormat: external_exports.string().optional()
9794
+ }).strict().refine((value) => Boolean(value.format || value.perdefinedFormat), {
9795
+ message: "date serial part requires format or perdefinedFormat"
9796
+ })
9797
+ }).strict();
9798
+ var serialPartBuildinSerialSchema = external_exports.object({
9799
+ mode: external_exports.literal("buildin"),
9800
+ type: external_exports.literal("serial"),
9801
+ options: external_exports.object({
9802
+ length: external_exports.number().int().min(1),
9803
+ lenfixed: external_exports.boolean().optional(),
9804
+ random: external_exports.boolean().optional(),
9805
+ reset: external_exports.string().optional()
9806
+ }).strict()
9807
+ }).strict();
9808
+ var serialPartFieldSchema = external_exports.object({
9809
+ mode: external_exports.literal("field"),
9810
+ field_id: external_exports.number().int().min(1001)
9811
+ }).passthrough();
9812
+ var serialPartSchema = external_exports.union([
9813
+ serialPartBuildinStringSchema,
9814
+ serialPartBuildinDateSchema,
9815
+ serialPartBuildinSerialSchema,
9816
+ serialPartFieldSchema
9817
+ ]);
9818
+ var fieldCommonShape = {
9819
+ id: external_exports.number().int().min(1001),
9820
+ label: external_exports.string().min(1),
9821
+ required: external_exports.boolean(),
9822
+ unique: external_exports.boolean(),
9823
+ editable: external_exports.boolean(),
9824
+ visible: external_exports.boolean(),
9825
+ show_label: external_exports.boolean(),
9826
+ scannable: external_exports.boolean(),
9827
+ default_value_mode: external_exports.number(),
9828
+ description: external_exports.string(),
9829
+ value: external_exports.any(),
9830
+ number_decimal: external_exports.number().int().min(0),
9831
+ depends: external_exports.array(external_exports.number().int().min(1001)),
9832
+ key: external_exports.string(),
9833
+ code_index: external_exports.boolean(),
9834
+ transfers: external_exports.array(external_exports.any()).nullable()
9835
+ };
9836
+ function isRecord(value) {
9837
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9838
+ }
9839
+ function cloneJSON(value) {
9840
+ return JSON.parse(JSON.stringify(value));
9841
+ }
9842
+ function makeSimpleFieldSchema(type) {
9843
+ return external_exports.object({
9844
+ ...fieldCommonShape,
9845
+ type: external_exports.literal(type),
9846
+ options: external_exports.record(external_exports.string(), external_exports.any()).nullable(),
9847
+ children: external_exports.null()
9848
+ }).strict();
9849
+ }
9850
+ function makeEnumFieldSchema(type) {
9851
+ const itemSchema = type === "status" ? statusItemSchema : enumItemSchema;
9852
+ return external_exports.object({
9853
+ ...fieldCommonShape,
9854
+ type: external_exports.literal(type),
9855
+ options: external_exports.object({
9856
+ options: external_exports.object({
9857
+ items: external_exports.array(itemSchema).min(1)
9858
+ }).passthrough()
9859
+ }).passthrough(),
9860
+ children: external_exports.null()
9861
+ }).strict();
9862
+ }
9863
+ var simpleFieldSchemas = simpleFieldTypes.map((type) => makeSimpleFieldSchema(type));
9864
+ var enumFieldSchemas = enumFieldTypes.map((type) => makeEnumFieldSchema(type));
9865
+ var formulaFieldSchema = external_exports.object({
9866
+ ...fieldCommonShape,
9867
+ type: external_exports.literal("formula"),
9868
+ options: external_exports.object({
9869
+ formula: formulaSchema
9870
+ }).passthrough(),
9871
+ children: external_exports.null()
9872
+ }).strict();
9873
+ var relationFieldSchemas = relationFieldTypes.map(
9874
+ (type) => external_exports.object({
9875
+ ...fieldCommonShape,
9876
+ type: external_exports.literal(type),
9877
+ options: external_exports.object({
9878
+ relation: relationOptionsSchema,
9879
+ mode: linkModeSchema.optional(),
9880
+ structure: linkStructureSchema.optional(),
9881
+ multiple: external_exports.boolean().optional(),
9882
+ backfill: external_exports.array(external_exports.object({
9883
+ id: external_exports.number().int().min(1001),
9884
+ local_id: external_exports.number().int().min(1001)
9885
+ }).strict()).optional(),
9886
+ addValue: external_exports.boolean().optional(),
9887
+ placeholder: external_exports.string().optional()
9888
+ }).passthrough(),
9889
+ children: external_exports.null()
9890
+ }).strict()
9891
+ );
9892
+ var lookupFieldSchema = external_exports.object({
9893
+ ...fieldCommonShape,
9894
+ type: external_exports.literal("lookup"),
9895
+ options: external_exports.object({
9896
+ relation: lookupRelationSchema
9897
+ }).passthrough(),
9898
+ children: external_exports.null()
9899
+ }).strict();
9900
+ var relationFieldFieldSchema = external_exports.object({
9901
+ ...fieldCommonShape,
9902
+ type: external_exports.literal("relationfield"),
9903
+ options: external_exports.object({
9904
+ relation: relationFieldRelationSchema
9905
+ }).passthrough(),
9906
+ children: external_exports.null()
9907
+ }).strict();
9908
+ var rollupFieldSchema = external_exports.object({
9909
+ ...fieldCommonShape,
9910
+ type: external_exports.literal("rollup"),
9911
+ options: external_exports.object({
9912
+ relation: lookupRelationSchema,
9913
+ aggregation_formula: formulaSchema
9914
+ }).passthrough(),
9915
+ children: external_exports.null()
9916
+ }).strict();
9917
+ var serialNumberFieldSchema = external_exports.object({
9918
+ ...fieldCommonShape,
9919
+ type: external_exports.literal("serialnumber"),
9920
+ options: external_exports.object({
9921
+ parts: external_exports.array(serialPartSchema).min(1)
9922
+ }).passthrough(),
9923
+ children: external_exports.null()
9924
+ }).strict();
9925
+ var genericFieldSchema = external_exports.object({
9926
+ ...fieldCommonShape,
9927
+ type: external_exports.string().min(1).refine((value) => !strictFieldTypes.has(value), {
9928
+ message: "known field type must use dedicated schema"
9929
+ }),
9930
+ options: external_exports.record(external_exports.string(), external_exports.any()).nullable(),
9931
+ children: external_exports.null()
9932
+ }).strict();
9933
+ var baseFieldSchemaVariants = [
9934
+ ...simpleFieldSchemas,
9935
+ ...enumFieldSchemas,
9936
+ ...relationFieldSchemas,
9937
+ formulaFieldSchema,
9938
+ lookupFieldSchema,
9939
+ relationFieldFieldSchema,
9940
+ rollupFieldSchema,
9941
+ serialNumberFieldSchema,
9942
+ genericFieldSchema
9943
+ ];
9944
+ var BaseFieldSchema = external_exports.union(baseFieldSchemaVariants);
9945
+ var SubformFieldSchema = external_exports.lazy(
9946
+ () => external_exports.object({
9947
+ ...fieldCommonShape,
9948
+ type: external_exports.literal("subform"),
9949
+ options: external_exports.record(external_exports.string(), external_exports.any()).nullable(),
9950
+ children: external_exports.array(BaseFieldSchema),
9951
+ layout: external_exports.array(external_exports.array(external_exports.number().int().min(1001))).optional()
9952
+ }).strict()
9953
+ );
9954
+ var FieldVOSchema = external_exports.lazy(
9955
+ () => external_exports.union([
9956
+ SubformFieldSchema,
9957
+ BaseFieldSchema
9958
+ ])
9959
+ );
9960
+ function normalizeEntitySaveInput(value) {
9961
+ if (!isRecord(value)) {
9962
+ return value;
9963
+ }
9964
+ const entity = cloneJSON(value);
9965
+ if (entity.layout === null) {
9966
+ entity.layout = [];
9967
+ }
9968
+ if (entity.current_serial === null) {
9969
+ delete entity.current_serial;
9970
+ }
9971
+ if (isRecord(entity.options)) {
9972
+ if (entity.options.Buttons === null) {
9973
+ entity.options.Buttons = [];
9974
+ }
9975
+ if (entity.options.CustomActions === null) {
9976
+ entity.options.CustomActions = [];
9977
+ }
9978
+ if (entity.options.FrontendEvents === null) {
9979
+ entity.options.FrontendEvents = [];
9980
+ }
9981
+ if (entity.options.misc === null) {
9982
+ entity.options.misc = {};
9983
+ }
9984
+ if (isRecord(entity.options.TitleFormat)) {
9985
+ if (entity.options.TitleFormat.Fields === null) {
9986
+ entity.options.TitleFormat.Fields = [];
9987
+ }
9988
+ if (entity.options.TitleFormat.Parts === null) {
9989
+ entity.options.TitleFormat.Parts = [];
9990
+ }
9991
+ }
9992
+ }
9993
+ return entity;
9994
+ }
9995
+ function collectAllFieldIds(fields) {
9996
+ const out = [];
9997
+ for (const field of fields) {
9998
+ out.push(field.id);
9999
+ if (field.type === "subform" && Array.isArray(field.children)) {
10000
+ for (const child of field.children) {
10001
+ out.push(child.id);
10002
+ }
10003
+ }
10004
+ }
10005
+ return out;
10006
+ }
10007
+ function collectTopLevelFieldIds(fields) {
10008
+ return fields.map((field) => field.id);
10009
+ }
10010
+ function extractFormulaFieldIds(value) {
10011
+ if (!value || typeof value !== "string") return [];
10012
+ const ids = [...value.matchAll(/:(\d+)\]\]/g)].map((match) => Number(match[1]));
10013
+ return ids.filter((id) => Number.isInteger(id) && id > 0);
10014
+ }
10015
+ var EntitySaveReqVOBaseSchema = external_exports.object({
10016
+ app_id: external_exports.number().optional(),
10017
+ current_serial: EntitySerialUpdaterVOSchema.optional(),
10018
+ field_id_seq: external_exports.number().int(),
10019
+ fields: external_exports.array(FieldVOSchema),
10020
+ id: external_exports.number().optional(),
10021
+ layout: external_exports.array(external_exports.array(external_exports.number().int().min(1001))).optional(),
10022
+ name: external_exports.string().optional(),
10023
+ options: EntityOptionsSchema.optional(),
10024
+ prototypes: external_exports.array(external_exports.number()).optional(),
10025
+ schema_version: external_exports.number().optional(),
10026
+ workflow_enabled: external_exports.boolean().optional()
10027
+ }).strict().superRefine((entity, ctx) => {
10028
+ const fields = entity.fields;
10029
+ const topLevelIds = new Set(collectTopLevelFieldIds(fields));
10030
+ const allIds = collectAllFieldIds(fields);
10031
+ const allIdSet = /* @__PURE__ */ new Set();
10032
+ for (const id of allIds) {
10033
+ if (allIdSet.has(id)) {
10034
+ ctx.addIssue({
10035
+ code: external_exports.ZodIssueCode.custom,
10036
+ path: ["fields"],
10037
+ message: `duplicate field id: ${id}`
10038
+ });
10039
+ }
10040
+ allIdSet.add(id);
10041
+ }
10042
+ const maxFieldId = allIds.length > 0 ? Math.max(...allIds) : 1e3;
10043
+ if (entity.field_id_seq <= maxFieldId) {
10044
+ ctx.addIssue({
10045
+ code: external_exports.ZodIssueCode.custom,
10046
+ path: ["field_id_seq"],
10047
+ message: `field_id_seq must be greater than max field id ${maxFieldId}`
10048
+ });
10049
+ }
10050
+ for (const [rowIndex, row] of (entity.layout ?? []).entries()) {
10051
+ for (const [colIndex, fieldId] of row.entries()) {
10052
+ if (!topLevelIds.has(fieldId)) {
10053
+ ctx.addIssue({
10054
+ code: external_exports.ZodIssueCode.custom,
10055
+ path: ["layout", rowIndex, colIndex],
10056
+ message: `layout references unknown top-level field id ${fieldId}`
10057
+ });
10058
+ }
10059
+ }
10060
+ }
10061
+ for (const [fieldIndex, field] of fields.entries()) {
10062
+ if (field.type !== "subform" && field.children !== null) {
10063
+ ctx.addIssue({
10064
+ code: external_exports.ZodIssueCode.custom,
10065
+ path: ["fields", fieldIndex, "children"],
10066
+ message: "only subform field can define children"
10067
+ });
10068
+ }
10069
+ if (field.type === "subform") {
10070
+ const childIds = new Set((field.children ?? []).map((child) => child.id));
10071
+ for (const [rowIndex, row] of (field.layout ?? []).entries()) {
10072
+ for (const [colIndex, fieldId] of row.entries()) {
10073
+ if (!childIds.has(fieldId)) {
10074
+ ctx.addIssue({
10075
+ code: external_exports.ZodIssueCode.custom,
10076
+ path: ["fields", fieldIndex, "layout", rowIndex, colIndex],
10077
+ message: `subform layout references non-child field id ${fieldId}`
10078
+ });
10079
+ }
10080
+ }
10081
+ }
10082
+ }
10083
+ if (field.type === "lookup" || field.type === "rollup") {
10084
+ const localLinktoFieldId = field.options?.relation?.local_linkto_field_id;
10085
+ if (typeof localLinktoFieldId === "number") {
10086
+ const target = fields.find((item) => item.id === localLinktoFieldId);
10087
+ if (!target || target.type !== "linkto") {
10088
+ ctx.addIssue({
10089
+ code: external_exports.ZodIssueCode.custom,
10090
+ path: ["fields", fieldIndex, "options", "relation", "local_linkto_field_id"],
10091
+ message: "local_linkto_field_id must reference a linkto field"
10092
+ });
10093
+ }
10094
+ }
10095
+ }
10096
+ if (field.type === "formula" || field.type === "rollup") {
10097
+ const formulaCode = field.type === "formula" ? field.options?.formula?.code : field.options?.aggregation_formula?.code;
10098
+ for (const referencedFieldId of extractFormulaFieldIds(formulaCode)) {
10099
+ if (!allIdSet.has(referencedFieldId)) {
10100
+ ctx.addIssue({
10101
+ code: external_exports.ZodIssueCode.custom,
10102
+ path: ["fields", fieldIndex, "options"],
10103
+ message: `formula references unknown field id ${referencedFieldId}`
10104
+ });
10105
+ }
10106
+ }
10107
+ }
10108
+ }
10109
+ });
10110
+ var EntitySaveReqVOSchemaOverride = external_exports.preprocess(normalizeEntitySaveInput, EntitySaveReqVOBaseSchema);
10111
+ var queryOrderSchema = external_exports.object({
10112
+ column: external_exports.string().min(1),
10113
+ order: external_exports.string().min(1)
10114
+ }).strict();
10115
+ var AppCreateByTenantsReqVOSchemaOverride = external_exports.object({
10116
+ icon_color: external_exports.string().optional(),
10117
+ icon_name: external_exports.string().optional(),
10118
+ name: external_exports.string().min(1).max(20)
10119
+ }).strict();
10120
+ var EntityQueryReqVOSchemaOverride = external_exports.object({
10121
+ limit: external_exports.number().int().positive().optional(),
10122
+ offset: external_exports.number().int().min(0).optional(),
10123
+ policy_id: external_exports.string().optional(),
10124
+ search: external_exports.record(external_exports.string(), external_exports.any()).optional(),
10125
+ sorts: external_exports.array(queryOrderSchema).optional(),
10126
+ view_mode: external_exports.string().optional(),
10127
+ viewMode: external_exports.never().optional(),
10128
+ withSubForm: external_exports.boolean().optional()
10129
+ }).strict();
10130
+ var InsertReqVOSchemaOverride = external_exports.object({
10131
+ policy_id: external_exports.string().optional(),
10132
+ fields: external_exports.record(external_exports.string(), external_exports.any())
10133
+ }).strict().superRefine((body, ctx) => {
10134
+ for (const key of Object.keys(body.fields ?? {})) {
10135
+ if (!/^\d+$/.test(key)) {
10136
+ ctx.addIssue({
10137
+ code: external_exports.ZodIssueCode.custom,
10138
+ path: ["fields", key],
10139
+ message: "row fields must use numeric field ids as keys"
10140
+ });
10141
+ }
10142
+ }
10143
+ });
10144
+ var EntityUpdateReqVOSchemaOverride = external_exports.object({
10145
+ changed_fields: external_exports.array(external_exports.number().int().positive()).min(1),
10146
+ data: external_exports.record(external_exports.string(), external_exports.any()),
10147
+ policy_id: external_exports.string().optional(),
10148
+ tags: external_exports.array(external_exports.string()).optional(),
10149
+ fields: external_exports.never().optional()
10150
+ }).strict().superRefine((body, ctx) => {
10151
+ const dataFieldIds = /* @__PURE__ */ new Set();
10152
+ for (const key of Object.keys(body.data ?? {})) {
10153
+ if (!/^\d+$/.test(key)) {
10154
+ ctx.addIssue({
10155
+ code: external_exports.ZodIssueCode.custom,
10156
+ path: ["data", key],
10157
+ message: "row data must use numeric field ids as keys"
10158
+ });
10159
+ continue;
10160
+ }
10161
+ dataFieldIds.add(Number(key));
10162
+ }
10163
+ for (const [index, fieldId] of body.changed_fields.entries()) {
10164
+ if (!dataFieldIds.has(fieldId)) {
10165
+ ctx.addIssue({
10166
+ code: external_exports.ZodIssueCode.custom,
10167
+ path: ["changed_fields", index],
10168
+ message: `changed_fields references ${fieldId}, but data does not contain that field id`
10169
+ });
10170
+ }
10171
+ }
10172
+ });
10173
+ var entitySelectionSortSchema = external_exports.object({
10174
+ column: external_exports.string().min(1),
10175
+ order: external_exports.string().min(1)
10176
+ }).strict();
10177
+ var entitySelectionIdsSchema = external_exports.object({
10178
+ type: external_exports.literal("ids"),
10179
+ ids: external_exports.array(external_exports.number().int().positive()).min(1),
10180
+ length: external_exports.number().int().positive().optional(),
10181
+ sorts: external_exports.array(entitySelectionSortSchema).optional(),
10182
+ condition: external_exports.record(external_exports.string(), external_exports.any()).optional()
10183
+ }).strict().superRefine((selection, ctx) => {
10184
+ if (selection.length !== void 0 && selection.length !== selection.ids.length) {
10185
+ ctx.addIssue({
10186
+ code: external_exports.ZodIssueCode.custom,
10187
+ path: ["length"],
10188
+ message: "length must match ids.length when provided"
10189
+ });
10190
+ }
10191
+ });
10192
+ var entitySelectionConditionSchema = external_exports.object({
10193
+ type: external_exports.literal("condition"),
10194
+ length: external_exports.number().int().positive(),
10195
+ condition: external_exports.record(external_exports.string(), external_exports.any()).superRefine((condition, ctx) => {
10196
+ if (!Object.keys(condition).length) {
10197
+ ctx.addIssue({
10198
+ code: external_exports.ZodIssueCode.custom,
10199
+ message: "condition selection requires a non-empty condition object"
10200
+ });
10201
+ return;
10202
+ }
10203
+ if (condition.selectAll !== true) {
10204
+ ctx.addIssue({
10205
+ code: external_exports.ZodIssueCode.custom,
10206
+ path: ["selectAll"],
10207
+ message: "condition selection must set selectAll to true"
10208
+ });
10209
+ }
10210
+ const filterKeys = Object.keys(condition).filter((key) => key !== "selectAll");
10211
+ if (filterKeys.length === 0) {
10212
+ return;
10213
+ }
10214
+ const hasSupportedQueryKey = filterKeys.some((key) => key === "q" || key === "tab" || key.startsWith("filter_"));
10215
+ if (!hasSupportedQueryKey) {
10216
+ ctx.addIssue({
10217
+ code: external_exports.ZodIssueCode.custom,
10218
+ message: "condition selection extra keys must use q, tab, or filter_*"
10219
+ });
10220
+ }
10221
+ }),
10222
+ sorts: external_exports.array(entitySelectionSortSchema).optional(),
10223
+ ids: external_exports.array(external_exports.number().int().positive()).optional()
10224
+ }).strict();
10225
+ var entitySelectionAllSchema = external_exports.object({
10226
+ type: external_exports.literal("all"),
10227
+ length: external_exports.number().int().positive().optional(),
10228
+ ids: external_exports.array(external_exports.number().int().positive()).optional(),
10229
+ condition: external_exports.record(external_exports.string(), external_exports.any()).optional(),
10230
+ sorts: external_exports.array(entitySelectionSortSchema).optional()
10231
+ }).strict();
10232
+ var entitySelectionSchema = external_exports.union([
10233
+ entitySelectionIdsSchema,
10234
+ entitySelectionConditionSchema,
10235
+ entitySelectionAllSchema
10236
+ ]);
10237
+ var entitySelectionLooseSchema = external_exports.union([
10238
+ entitySelectionSchema,
10239
+ entitySelectionAllSchema
10240
+ ]);
10241
+ var EntitySelectionActionReqVOSchemaOverride = external_exports.lazy(
10242
+ () => external_exports.object({
10243
+ limit: external_exports.number().int().positive().optional(),
10244
+ offset: external_exports.number().int().min(0).optional(),
10245
+ policy_id: external_exports.string().optional(),
10246
+ selection: entitySelectionSchema
10247
+ }).strict()
10248
+ );
10249
+ var bulkUpdateActionSchema = external_exports.object({
10250
+ type: external_exports.string().min(1),
10251
+ value: external_exports.any().optional(),
10252
+ text_search: external_exports.string().optional(),
10253
+ text_replace: external_exports.string().optional(),
10254
+ text_append: external_exports.string().optional(),
10255
+ text_prepend: external_exports.string().optional(),
10256
+ number_add: external_exports.number().optional(),
10257
+ number_mul: external_exports.number().optional(),
10258
+ number_sub: external_exports.number().optional(),
10259
+ datetime_add: external_exports.number().optional(),
10260
+ datetime_sub: external_exports.number().optional()
10261
+ }).strict().superRefine((action, ctx) => {
10262
+ switch (action.type) {
10263
+ case "set":
10264
+ if (!("value" in action)) {
10265
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["value"], message: "set action requires value" });
10266
+ }
10267
+ break;
10268
+ case "text_replace":
10269
+ if (!action.text_search) {
10270
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["text_search"], message: "text_replace requires text_search" });
10271
+ }
10272
+ if (!action.text_replace) {
10273
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["text_replace"], message: "text_replace requires text_replace" });
10274
+ }
10275
+ break;
10276
+ case "text_append":
10277
+ if (!action.text_append) {
10278
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["text_append"], message: "text_append requires text_append" });
10279
+ }
10280
+ break;
10281
+ case "text_prepend":
10282
+ if (!action.text_prepend) {
10283
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["text_prepend"], message: "text_prepend requires text_prepend" });
10284
+ }
10285
+ break;
10286
+ case "number_add":
10287
+ if (typeof action.number_add !== "number") {
10288
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["number_add"], message: "number_add requires number_add" });
10289
+ }
10290
+ break;
10291
+ case "number_sub":
10292
+ if (typeof action.number_sub !== "number") {
10293
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["number_sub"], message: "number_sub requires number_sub" });
10294
+ }
10295
+ break;
10296
+ case "number_mul":
10297
+ if (typeof action.number_mul !== "number") {
10298
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["number_mul"], message: "number_mul requires number_mul" });
10299
+ }
10300
+ break;
10301
+ case "datetime_add":
10302
+ if (typeof action.datetime_add !== "number") {
10303
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["datetime_add"], message: "datetime_add requires datetime_add" });
10304
+ }
10305
+ break;
10306
+ case "datetime_sub":
10307
+ if (typeof action.datetime_sub !== "number") {
10308
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["datetime_sub"], message: "datetime_sub requires datetime_sub" });
10309
+ }
10310
+ break;
10311
+ case "datetime_now":
10312
+ case "formula":
10313
+ break;
10314
+ default:
10315
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["type"], message: `unsupported bulk update action type: ${action.type}` });
10316
+ }
10317
+ });
10318
+ var EntityBulkUpdateReqVOSchemaOverride = external_exports.object({
10319
+ policy_id: external_exports.string().optional(),
10320
+ selection: entitySelectionSchema,
10321
+ fields: external_exports.array(external_exports.object({
10322
+ id: external_exports.number().int().min(1001),
10323
+ action: bulkUpdateActionSchema
10324
+ }).strict()).min(1)
10325
+ }).strict();
10326
+ var EntityTagsSelectionReqVOSchemaOverride = external_exports.object({
10327
+ policy_id: external_exports.string(),
10328
+ selection: entitySelectionSchema
10329
+ }).strict();
10330
+ var EntityTagsBatchReqVOSchemaOverride = external_exports.object({
10331
+ policy_id: external_exports.string(),
10332
+ selection: entitySelectionSchema,
10333
+ tag_names: external_exports.array(external_exports.string().min(1)).min(1)
10334
+ }).strict();
10335
+ var EntityInvokeBatchOperatorReqVOSchemaOverride = external_exports.object({
10336
+ id: external_exports.string().min(1),
10337
+ data: external_exports.object({
10338
+ action_id: external_exports.string().min(1),
10339
+ policy_id: external_exports.string().optional(),
10340
+ selection: entitySelectionLooseSchema
10341
+ }).strict(),
10342
+ params: external_exports.record(external_exports.string(), external_exports.any()).optional()
10343
+ }).strict();
10344
+
9664
10345
  // src/runtime/zod_registry.ts
10346
+ var schemaOverrides = {
10347
+ AppCreateByTenantsReqVO: AppCreateByTenantsReqVOSchemaOverride,
10348
+ EntityBulkUpdateReqVO: EntityBulkUpdateReqVOSchemaOverride,
10349
+ "EntityInvokeBatchOperatorReqVO & InvokeRequestVO": EntityInvokeBatchOperatorReqVOSchemaOverride,
10350
+ EntityQueryReqVO: EntityQueryReqVOSchemaOverride,
10351
+ EntitySaveReqVO: EntitySaveReqVOSchemaOverride,
10352
+ EntitySelectionActionReqVO: EntitySelectionActionReqVOSchemaOverride,
10353
+ "{ policy_id: string selection: any }": EntityTagsSelectionReqVOSchemaOverride,
10354
+ "{ policy_id: string selection: any tag_names: string[] }": EntityTagsBatchReqVOSchemaOverride,
10355
+ EntityUpdateReqVO: EntityUpdateReqVOSchemaOverride,
10356
+ InsertReqVO: InsertReqVOSchemaOverride
10357
+ };
9665
10358
  function getBodySchema(typeName) {
9666
10359
  const name = String(typeName || "").trim();
9667
10360
  if (!name) return null;
10361
+ if (schemaOverrides[name]) {
10362
+ return schemaOverrides[name];
10363
+ }
9668
10364
  return bodySchemas[name] ?? null;
9669
10365
  }
9670
10366
  function getUnsupportedBodySchemaReason(typeName) {
@@ -9672,6 +10368,60 @@ function getUnsupportedBodySchemaReason(typeName) {
9672
10368
  if (!name) return null;
9673
10369
  return unsupportedBodySchemas[name] ?? null;
9674
10370
  }
10371
+ var examplesIndexDocHint = {
10372
+ title: "Examples index",
10373
+ file: "/opt/arcubase-sdk/docs/runtime-reference/examples/README.md"
10374
+ };
10375
+ var omsExampleDocHint = {
10376
+ title: "OMS example 01",
10377
+ file: "/opt/arcubase-sdk/docs/runtime-reference/examples/oms-01/README.md"
10378
+ };
10379
+ var docHintIndex = {
10380
+ AppCreateByTenantsReqVO: [
10381
+ { title: "Table lifecycle", file: "/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md" },
10382
+ examplesIndexDocHint,
10383
+ omsExampleDocHint
10384
+ ],
10385
+ AppCreateEntityReqVO: [
10386
+ { title: "Table lifecycle", file: "/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md" },
10387
+ examplesIndexDocHint,
10388
+ omsExampleDocHint
10389
+ ],
10390
+ EntitySaveReqVO: [
10391
+ { title: "Entity schema", file: "/opt/arcubase-sdk/docs/runtime-reference/entity-schema.md" },
10392
+ omsExampleDocHint
10393
+ ],
10394
+ EntityQueryReqVO: [
10395
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10396
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" },
10397
+ omsExampleDocHint
10398
+ ],
10399
+ EntityUpdateReqVO: [
10400
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10401
+ omsExampleDocHint
10402
+ ],
10403
+ EntitySelectionActionReqVO: [
10404
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" },
10405
+ omsExampleDocHint
10406
+ ],
10407
+ InsertReqVO: [
10408
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10409
+ omsExampleDocHint
10410
+ ],
10411
+ EntityBulkUpdateReqVO: [
10412
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" },
10413
+ omsExampleDocHint
10414
+ ],
10415
+ "EntityInvokeBatchOperatorReqVO & InvokeRequestVO": [
10416
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" }
10417
+ ],
10418
+ "{ policy_id: string selection: any }": [
10419
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" }
10420
+ ],
10421
+ "{ policy_id: string selection: any tag_names: string[] }": [
10422
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" }
10423
+ ]
10424
+ };
9675
10425
  function getTypeHints(typeName) {
9676
10426
  const name = String(typeName || "").trim();
9677
10427
  if (!name) return [];
@@ -9694,6 +10444,67 @@ function getTypeHints(typeName) {
9694
10444
  }
9695
10445
  return out;
9696
10446
  }
10447
+ function getDocHints(typeName) {
10448
+ const name = String(typeName || "").trim();
10449
+ if (!name) return [];
10450
+ return docHintIndex[name] ?? [];
10451
+ }
10452
+ var commandDocHintIndex = {
10453
+ "admin.app.createAppByTenants": [
10454
+ { title: "Table lifecycle", file: "/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md" },
10455
+ examplesIndexDocHint,
10456
+ omsExampleDocHint
10457
+ ],
10458
+ "admin.app.createEntity": [
10459
+ { title: "Table lifecycle", file: "/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md" },
10460
+ omsExampleDocHint
10461
+ ],
10462
+ "admin.entity.adminGetEntityInfo": [
10463
+ { title: "Table lifecycle", file: "/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md" },
10464
+ omsExampleDocHint
10465
+ ],
10466
+ "admin.entity.adminSaveEntity": [
10467
+ { title: "Entity schema", file: "/opt/arcubase-sdk/docs/runtime-reference/entity-schema.md" },
10468
+ omsExampleDocHint
10469
+ ],
10470
+ "user.workflow.insertEntity": [
10471
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10472
+ omsExampleDocHint
10473
+ ],
10474
+ "user.workflow.queryEntity": [
10475
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" },
10476
+ omsExampleDocHint
10477
+ ],
10478
+ "user.workflow.getEntityRow": [
10479
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10480
+ omsExampleDocHint
10481
+ ],
10482
+ "user.workflow.updateEntityRow": [
10483
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10484
+ omsExampleDocHint
10485
+ ],
10486
+ "user.workflow.queryEntitySelection": [
10487
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" },
10488
+ omsExampleDocHint
10489
+ ],
10490
+ "user.workflow.deleteEntityRow": [
10491
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10492
+ omsExampleDocHint
10493
+ ],
10494
+ "user.workflow.restoreEntityRow": [
10495
+ { title: "Row CRUD", file: "/opt/arcubase-sdk/docs/runtime-reference/row-crud.md" },
10496
+ omsExampleDocHint
10497
+ ],
10498
+ "user.entity.updateEntityBulk": [
10499
+ { title: "Search and bulk actions", file: "/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md" },
10500
+ omsExampleDocHint
10501
+ ]
10502
+ };
10503
+ function getCommandDocHints(operation) {
10504
+ const key = String(operation || "").trim();
10505
+ if (!key) return [];
10506
+ return commandDocHintIndex[key] ?? [];
10507
+ }
9697
10508
 
9698
10509
  // src/runtime/execute.ts
9699
10510
  function renderRootHelp(scope) {
@@ -9708,7 +10519,8 @@ function renderRootHelp(scope) {
9708
10519
  function renderModuleHelp(scope, moduleName) {
9709
10520
  const items = listModuleCommands(scope, moduleName);
9710
10521
  if (items.length === 0) {
9711
- throw new CLIError("UNKNOWN_MODULE", `unknown module: ${moduleName}`, 2);
10522
+ const suggestions = findCommandSuggestions(moduleName, "").map((item) => `${item.binary} ${item.moduleName} ${item.commandName}`);
10523
+ throw new CLIError("UNKNOWN_MODULE", `unknown module: ${moduleName}`, 2, suggestions.length > 0 ? { suggestions } : void 0);
9712
10524
  }
9713
10525
  return [
9714
10526
  `${scope === "admin" ? "arcubase-admin" : "arcubase"} ${moduleName} <command> [flags]`,
@@ -9720,15 +10532,22 @@ function renderModuleHelp(scope, moduleName) {
9720
10532
  function renderCommandHelp(scope, moduleName, commandName) {
9721
10533
  const command = findCommand(scope, moduleName, commandName);
9722
10534
  if (!command) {
9723
- throw new CLIError("UNKNOWN_COMMAND", `unknown command: ${moduleName} ${commandName}`, 2);
10535
+ const suggestions = findCommandSuggestions(moduleName, commandName).map((item) => `${item.binary} ${item.moduleName} ${item.commandName}`);
10536
+ throw new CLIError("UNKNOWN_COMMAND", `unknown command: ${moduleName} ${commandName}`, 2, suggestions.length > 0 ? { suggestions } : void 0);
9724
10537
  }
10538
+ const docHints = [
10539
+ ...getCommandDocHints(`${scope}.${command.module}.${command.functionName}`),
10540
+ ...command.requestType ? getDocHints(command.requestType) : []
10541
+ ].filter((item, index, list) => list.findIndex((candidate) => candidate.file === item.file) === index);
9725
10542
  return [
9726
10543
  `${scope === "admin" ? "arcubase-admin" : "arcubase"} ${moduleName} ${commandName}`,
9727
10544
  `method: ${command.method}`,
9728
10545
  `endpoint: ${normalizeExternalEndpoint(command.endpoint)}`,
9729
10546
  command.requestType ? `body: ${command.requestType} via --body-file` : "body: none",
10547
+ "query flags: --query-file",
9730
10548
  command.endpointParams.length ? `path flags: ${command.endpointParams.map((item) => `--${item.replace(/_/g, "-")}`).join(", ")}` : "path flags: none",
9731
- command.scalarParams.length ? `scalar flags: ${command.scalarParams.map((item) => `--${item.name.replace(/([A-Z])/g, "-$1").toLowerCase()}`).join(", ")}` : "scalar flags: none"
10549
+ command.scalarParams.length ? `scalar flags: ${command.scalarParams.map((item) => `--${item.name.replace(/([A-Z])/g, "-$1").toLowerCase()}`).join(", ")}` : "scalar flags: none",
10550
+ ...docHints.length > 0 ? ["docs:", ...docHints.map((item) => ` - ${item.title}: ${item.file}`)] : []
9732
10551
  ].join("\n");
9733
10552
  }
9734
10553
  function coerceScalar(value, typeText) {
@@ -9772,7 +10591,69 @@ function buildScalarQuery(command, flags) {
9772
10591
  }
9773
10592
  return Object.keys(out).length > 0 ? out : void 0;
9774
10593
  }
9775
- async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl = fetch) {
10594
+ function isRecord2(value) {
10595
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
10596
+ }
10597
+ function throwBodyValidationFailure(message, requestType, path, scope, command) {
10598
+ throw new CLIError("BODY_VALIDATION_FAILED", message, 2, {
10599
+ operation: `${scope}.${command.module}.${command.functionName}`,
10600
+ requestType,
10601
+ issues: [
10602
+ {
10603
+ path,
10604
+ message
10605
+ }
10606
+ ],
10607
+ tsHints: getTypeHints(requestType),
10608
+ docHints: getDocHints(requestType)
10609
+ });
10610
+ }
10611
+ function validateActionSpecificBody(scope, command, flags, body) {
10612
+ if (!isRecord2(body) || !command.requestType) {
10613
+ return;
10614
+ }
10615
+ if (command.module === "workflow" && command.functionName === "queryEntitySelection") {
10616
+ const action = flagValue(flags, "action");
10617
+ const selection = body.selection;
10618
+ if (!isRecord2(selection) || typeof selection.type !== "string") {
10619
+ return;
10620
+ }
10621
+ const type = selection.type;
10622
+ const condition = isRecord2(selection.condition) ? selection.condition : void 0;
10623
+ const conditionKeys = condition ? Object.keys(condition).filter((key) => key !== "selectAll") : [];
10624
+ if (action === "query") {
10625
+ if (type === "condition") {
10626
+ throwBodyValidationFailure(
10627
+ "selection.type=condition is not supported for action=query; use selection.type=ids or selection.type=all, or use workflow query-entity for search conditions",
10628
+ command.requestType,
10629
+ "body.selection.type",
10630
+ scope,
10631
+ command
10632
+ );
10633
+ }
10634
+ return;
10635
+ }
10636
+ if ((action === "archive" || action === "delete" || action === "batch_print") && type === "all") {
10637
+ throwBodyValidationFailure(
10638
+ `selection.type=all is not supported for action=${action}; use ids or condition`,
10639
+ command.requestType,
10640
+ "body.selection.type",
10641
+ scope,
10642
+ command
10643
+ );
10644
+ }
10645
+ if ((action === "archive" || action === "delete") && type === "condition" && conditionKeys.length === 0) {
10646
+ throwBodyValidationFailure(
10647
+ `selection.condition for action=${action} requires at least one q, tab, or filter_* key in addition to selectAll`,
10648
+ command.requestType,
10649
+ "body.selection.condition",
10650
+ scope,
10651
+ command
10652
+ );
10653
+ }
10654
+ }
10655
+ }
10656
+ async function executeCLI(scope, argv, env, fetchImpl = fetch) {
9776
10657
  const parsed = parseCLIArgs(argv);
9777
10658
  if (parsed.commandTokens.length === 0) {
9778
10659
  return { kind: "help", text: renderRootHelp(scope) };
@@ -9787,6 +10668,7 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9787
10668
  if (hasFlag(parsed.flags, "help")) {
9788
10669
  return { kind: "help", text: renderCommandHelp(scope, moduleName, commandName) };
9789
10670
  }
10671
+ const runtimeEnv = env ?? loadRuntimeEnv(scope);
9790
10672
  const command = findCommand(scope, moduleName, commandName);
9791
10673
  if (!command) {
9792
10674
  throw new CLIError("UNKNOWN_COMMAND", `unknown command: ${moduleName} ${commandName}`, 2);
@@ -9796,6 +10678,7 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9796
10678
  const fileQuery = loadQueryFromFlags(parsed.flags);
9797
10679
  const query = { ...scalarQuery ?? {}, ...fileQuery ?? {} };
9798
10680
  const body = loadBodyFromFlags(parsed.flags);
10681
+ let validatedBody = body;
9799
10682
  if (command.requestType) {
9800
10683
  if (body === void 0) {
9801
10684
  throw new CLIError("MISSING_BODY_FILE", `command requires --body-file for ${command.requestType}`, 2);
@@ -9815,10 +10698,13 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9815
10698
  path: issue.path.length > 0 ? `body.${issue.path.join(".")}` : "body",
9816
10699
  message: issue.message
9817
10700
  })),
9818
- tsHints: getTypeHints(command.requestType)
10701
+ tsHints: getTypeHints(command.requestType),
10702
+ docHints: getDocHints(command.requestType)
9819
10703
  }
9820
10704
  );
9821
10705
  }
10706
+ validatedBody = parsedBody.data;
10707
+ validateActionSpecificBody(scope, command, parsed.flags, validatedBody);
9822
10708
  } else {
9823
10709
  const unsupportedReason = getUnsupportedBodySchemaReason(command.requestType);
9824
10710
  if (unsupportedReason) {
@@ -9826,19 +10712,19 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9826
10712
  operation: `${scope}.${command.module}.${command.functionName}`,
9827
10713
  requestType: command.requestType,
9828
10714
  reason: unsupportedReason,
9829
- tsHints: getTypeHints(command.requestType)
10715
+ tsHints: getTypeHints(command.requestType),
10716
+ docHints: getDocHints(command.requestType)
9830
10717
  });
9831
10718
  }
9832
10719
  }
9833
10720
  }
9834
- const headers = buildRequestHeaders(env);
9835
- const response = await fetchImpl(buildURL(env.ARCUBASE_BASE_URL, endpoint, Object.keys(query).length > 0 ? query : void 0), {
10721
+ const response = await fetchImpl(buildURL(runtimeEnv.ARCUBASE_BASE_URL, endpoint, Object.keys(query).length > 0 ? query : void 0), {
9836
10722
  method: command.method,
9837
10723
  headers: {
9838
- ...headers,
10724
+ ...buildRequestHeaders(runtimeEnv),
9839
10725
  "Content-Type": "application/json"
9840
10726
  },
9841
- body: body === void 0 || command.method === "GET" ? void 0 : JSON.stringify(body)
10727
+ body: validatedBody === void 0 || command.method === "GET" ? void 0 : JSON.stringify(validatedBody)
9842
10728
  });
9843
10729
  const raw = await response.text();
9844
10730
  let parsedResponse = raw;
@@ -9849,6 +10735,17 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9849
10735
  if (!response.ok) {
9850
10736
  throw new CLIError("UPSTREAM_REQUEST_FAILED", typeof parsedResponse === "string" ? parsedResponse : JSON.stringify(parsedResponse), 1);
9851
10737
  }
10738
+ if (parsedResponse && typeof parsedResponse === "object" && "error" in parsedResponse && parsedResponse.error) {
10739
+ const upstreamError = parsedResponse.error;
10740
+ const upstreamMessage = typeof upstreamError === "object" && upstreamError && "message" in upstreamError && typeof upstreamError.message === "string" ? upstreamError.message : typeof upstreamError === "string" ? upstreamError : JSON.stringify(upstreamError);
10741
+ const traceId = typeof parsedResponse.trace_id === "string" ? parsedResponse.trace_id : typeof parsedResponse.request_id === "string" ? parsedResponse.request_id : void 0;
10742
+ throw new CLIError("UPSTREAM_BODY_ERROR", upstreamMessage, 1, {
10743
+ endpoint,
10744
+ method: command.method,
10745
+ traceId,
10746
+ upstreamError
10747
+ });
10748
+ }
9852
10749
  return {
9853
10750
  kind: "result",
9854
10751
  commandPath: command.commandPath,