@carthooks/arcubase-cli 0.1.1 → 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 (105) hide show
  1. package/bundle/arcubase-admin.mjs +911 -10
  2. package/bundle/arcubase.mjs +911 -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/env.d.ts +1 -0
  10. package/dist/runtime/env.d.ts.map +1 -1
  11. package/dist/runtime/env.js +1 -0
  12. package/dist/runtime/errors.d.ts +10 -0
  13. package/dist/runtime/errors.d.ts.map +1 -1
  14. package/dist/runtime/execute.d.ts.map +1 -1
  15. package/dist/runtime/execute.js +89 -10
  16. package/dist/runtime/http.d.ts +1 -1
  17. package/dist/runtime/http.d.ts.map +1 -1
  18. package/dist/runtime/http.js +3 -0
  19. package/dist/runtime/zod_registry.d.ts +6 -0
  20. package/dist/runtime/zod_registry.d.ts.map +1 -1
  21. package/dist/runtime/zod_registry.js +133 -0
  22. package/dist/tests/bootstrap.test.js +5 -0
  23. package/dist/tests/command_registry.test.js +5 -0
  24. package/dist/tests/entity_save_schema.test.d.ts +2 -0
  25. package/dist/tests/entity_save_schema.test.d.ts.map +1 -0
  26. package/dist/tests/entity_save_schema.test.js +221 -0
  27. package/dist/tests/execute_validation.test.js +453 -1
  28. package/dist/tests/help.test.js +33 -0
  29. package/package.json +1 -1
  30. package/sdk-dist/docs/runtime-reference/README.md +177 -0
  31. package/sdk-dist/docs/runtime-reference/entity-schema/README.md +120 -0
  32. package/sdk-dist/docs/runtime-reference/entity-schema/address.md +34 -0
  33. package/sdk-dist/docs/runtime-reference/entity-schema/boolean.md +37 -0
  34. package/sdk-dist/docs/runtime-reference/entity-schema/button.md +47 -0
  35. package/sdk-dist/docs/runtime-reference/entity-schema/checkbox.md +61 -0
  36. package/sdk-dist/docs/runtime-reference/entity-schema/datasets.md +35 -0
  37. package/sdk-dist/docs/runtime-reference/entity-schema/datetime.md +40 -0
  38. package/sdk-dist/docs/runtime-reference/entity-schema/department.md +33 -0
  39. package/sdk-dist/docs/runtime-reference/entity-schema/departments.md +34 -0
  40. package/sdk-dist/docs/runtime-reference/entity-schema/divider.md +39 -0
  41. package/sdk-dist/docs/runtime-reference/entity-schema/file.md +44 -0
  42. package/sdk-dist/docs/runtime-reference/entity-schema/formula.md +44 -0
  43. package/sdk-dist/docs/runtime-reference/entity-schema/image.md +43 -0
  44. package/sdk-dist/docs/runtime-reference/entity-schema/linkto.md +67 -0
  45. package/sdk-dist/docs/runtime-reference/entity-schema/location.md +32 -0
  46. package/sdk-dist/docs/runtime-reference/entity-schema/lookup.md +41 -0
  47. package/sdk-dist/docs/runtime-reference/entity-schema/member.md +37 -0
  48. package/sdk-dist/docs/runtime-reference/entity-schema/members.md +31 -0
  49. package/sdk-dist/docs/runtime-reference/entity-schema/number.md +70 -0
  50. package/sdk-dist/docs/runtime-reference/entity-schema/query.md +50 -0
  51. package/sdk-dist/docs/runtime-reference/entity-schema/radio.md +53 -0
  52. package/sdk-dist/docs/runtime-reference/entity-schema/relation.md +55 -0
  53. package/sdk-dist/docs/runtime-reference/entity-schema/relationfield.md +38 -0
  54. package/sdk-dist/docs/runtime-reference/entity-schema/rollup.md +54 -0
  55. package/sdk-dist/docs/runtime-reference/entity-schema/select.md +63 -0
  56. package/sdk-dist/docs/runtime-reference/entity-schema/selects.md +51 -0
  57. package/sdk-dist/docs/runtime-reference/entity-schema/serialnumber.md +48 -0
  58. package/sdk-dist/docs/runtime-reference/entity-schema/signature.md +31 -0
  59. package/sdk-dist/docs/runtime-reference/entity-schema/status.md +70 -0
  60. package/sdk-dist/docs/runtime-reference/entity-schema/subform.md +74 -0
  61. package/sdk-dist/docs/runtime-reference/entity-schema/tags.md +19 -0
  62. package/sdk-dist/docs/runtime-reference/entity-schema/text.md +76 -0
  63. package/sdk-dist/docs/runtime-reference/entity-schema/textarea.md +47 -0
  64. package/sdk-dist/docs/runtime-reference/entity-schema/workflow_status.md +17 -0
  65. package/sdk-dist/docs/runtime-reference/entity-schema.md +197 -0
  66. package/sdk-dist/docs/runtime-reference/examples/README.md +51 -0
  67. package/sdk-dist/docs/runtime-reference/examples/crm-01/README.md +20 -0
  68. package/sdk-dist/docs/runtime-reference/examples/mes-01/README.md +21 -0
  69. package/sdk-dist/docs/runtime-reference/examples/oms-01/README.md +164 -0
  70. package/sdk-dist/docs/runtime-reference/examples/oms-01/app-overview.md +79 -0
  71. package/sdk-dist/docs/runtime-reference/examples/oms-01/create-app.json +3 -0
  72. package/sdk-dist/docs/runtime-reference/examples/oms-01/goods-receipt.create-entity.json +3 -0
  73. package/sdk-dist/docs/runtime-reference/examples/oms-01/goods-receipt.schema.json +159 -0
  74. package/sdk-dist/docs/runtime-reference/examples/oms-01/item-master.create-entity.json +3 -0
  75. package/sdk-dist/docs/runtime-reference/examples/oms-01/item-master.schema.json +179 -0
  76. package/sdk-dist/docs/runtime-reference/examples/oms-01/picking-list.create-entity.json +3 -0
  77. package/sdk-dist/docs/runtime-reference/examples/oms-01/picking-list.schema.json +168 -0
  78. package/sdk-dist/docs/runtime-reference/examples/oms-01/purchase-order.create-entity.json +3 -0
  79. package/sdk-dist/docs/runtime-reference/examples/oms-01/purchase-order.schema.json +417 -0
  80. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.bulk-update.json +22 -0
  81. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.create-entity.json +3 -0
  82. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.query.json +10 -0
  83. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.row.insert.json +28 -0
  84. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.schema.json +398 -0
  85. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.selection.condition.json +13 -0
  86. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.selection.ids.json +7 -0
  87. package/sdk-dist/docs/runtime-reference/examples/oms-01/stock-issue.create-entity.json +3 -0
  88. package/sdk-dist/docs/runtime-reference/examples/oms-01/stock-issue.schema.json +137 -0
  89. package/sdk-dist/docs/runtime-reference/examples/wms-01/README.md +21 -0
  90. package/sdk-dist/docs/runtime-reference/row-crud.md +186 -0
  91. package/sdk-dist/docs/runtime-reference/search-and-bulk-actions.md +494 -0
  92. package/sdk-dist/docs/runtime-reference/table-lifecycle.md +123 -0
  93. package/sdk-dist/docs/runtime-reference/workflow/README.md +19 -0
  94. package/src/runtime/command_registry.ts +47 -0
  95. package/src/runtime/entity_save_schema.ts +708 -0
  96. package/src/runtime/env.ts +2 -0
  97. package/src/runtime/errors.ts +11 -0
  98. package/src/runtime/execute.ts +123 -10
  99. package/src/runtime/http.ts +4 -1
  100. package/src/runtime/zod_registry.ts +154 -0
  101. package/src/tests/bootstrap.test.ts +5 -0
  102. package/src/tests/command_registry.test.ts +6 -0
  103. package/src/tests/entity_save_schema.test.ts +236 -0
  104. package/src/tests/execute_validation.test.ts +601 -1
  105. package/src/tests/help.test.ts +39 -0
@@ -94,6 +94,7 @@ function loadRuntimeEnv(scope, env = process.env) {
94
94
  ARCUBASE_BASE_URL: requiredValue(env, scope, "ARCUBASE_BASE_URL"),
95
95
  ARCUBASE_TENANT_ID: requiredValue(env, scope, "ARCUBASE_TENANT_ID"),
96
96
  ARCUBASE_ACCESS_TOKEN: requiredValue(env, scope, "ARCUBASE_ACCESS_TOKEN"),
97
+ ARCUBASE_HOST: optionalValue(env, scope, "ARCUBASE_HOST"),
97
98
  ARCUBASE_TRACE_ID: optionalValue(env, scope, "ARCUBASE_TRACE_ID"),
98
99
  ARCUBASE_SUBJECT_TYPE: optionalValue(env, scope, "ARCUBASE_SUBJECT_TYPE"),
99
100
  ARCUBASE_SUBJECT_ID: optionalValue(env, scope, "ARCUBASE_SUBJECT_ID"),
@@ -107,6 +108,9 @@ function buildRequestHeaders(env) {
107
108
  Authorization: `Bearer ${env.ARCUBASE_ACCESS_TOKEN}`,
108
109
  "X-Tenant-Id": env.ARCUBASE_TENANT_ID
109
110
  };
111
+ if (env.ARCUBASE_HOST && env.ARCUBASE_HOST.trim() !== "") {
112
+ headers["X-Host"] = env.ARCUBASE_HOST;
113
+ }
110
114
  if (env.ARCUBASE_TRACE_ID) {
111
115
  headers["X-Trace-Id"] = env.ARCUBASE_TRACE_ID;
112
116
  }
@@ -4734,6 +4738,41 @@ function listModules(scope) {
4734
4738
  function listModuleCommands(scope, moduleName) {
4735
4739
  return listCommands(scope).filter((item) => item.commandPath[0] === moduleName);
4736
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
+ }
4737
4776
 
4738
4777
  // src/runtime/body_loader.ts
4739
4778
  import fs from "fs";
@@ -9657,10 +9696,671 @@ var typeIndex = {
9657
9696
  }
9658
9697
  };
9659
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
+
9660
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
+ };
9661
10358
  function getBodySchema(typeName) {
9662
10359
  const name = String(typeName || "").trim();
9663
10360
  if (!name) return null;
10361
+ if (schemaOverrides[name]) {
10362
+ return schemaOverrides[name];
10363
+ }
9664
10364
  return bodySchemas[name] ?? null;
9665
10365
  }
9666
10366
  function getUnsupportedBodySchemaReason(typeName) {
@@ -9668,6 +10368,60 @@ function getUnsupportedBodySchemaReason(typeName) {
9668
10368
  if (!name) return null;
9669
10369
  return unsupportedBodySchemas[name] ?? null;
9670
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
+ };
9671
10425
  function getTypeHints(typeName) {
9672
10426
  const name = String(typeName || "").trim();
9673
10427
  if (!name) return [];
@@ -9690,6 +10444,67 @@ function getTypeHints(typeName) {
9690
10444
  }
9691
10445
  return out;
9692
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
+ }
9693
10508
 
9694
10509
  // src/runtime/execute.ts
9695
10510
  function renderRootHelp(scope) {
@@ -9704,7 +10519,8 @@ function renderRootHelp(scope) {
9704
10519
  function renderModuleHelp(scope, moduleName) {
9705
10520
  const items = listModuleCommands(scope, moduleName);
9706
10521
  if (items.length === 0) {
9707
- 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);
9708
10524
  }
9709
10525
  return [
9710
10526
  `${scope === "admin" ? "arcubase-admin" : "arcubase"} ${moduleName} <command> [flags]`,
@@ -9716,15 +10532,22 @@ function renderModuleHelp(scope, moduleName) {
9716
10532
  function renderCommandHelp(scope, moduleName, commandName) {
9717
10533
  const command = findCommand(scope, moduleName, commandName);
9718
10534
  if (!command) {
9719
- 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);
9720
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);
9721
10542
  return [
9722
10543
  `${scope === "admin" ? "arcubase-admin" : "arcubase"} ${moduleName} ${commandName}`,
9723
10544
  `method: ${command.method}`,
9724
10545
  `endpoint: ${normalizeExternalEndpoint(command.endpoint)}`,
9725
10546
  command.requestType ? `body: ${command.requestType} via --body-file` : "body: none",
10547
+ "query flags: --query-file",
9726
10548
  command.endpointParams.length ? `path flags: ${command.endpointParams.map((item) => `--${item.replace(/_/g, "-")}`).join(", ")}` : "path flags: none",
9727
- 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}`)] : []
9728
10551
  ].join("\n");
9729
10552
  }
9730
10553
  function coerceScalar(value, typeText) {
@@ -9768,7 +10591,69 @@ function buildScalarQuery(command, flags) {
9768
10591
  }
9769
10592
  return Object.keys(out).length > 0 ? out : void 0;
9770
10593
  }
9771
- 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) {
9772
10657
  const parsed = parseCLIArgs(argv);
9773
10658
  if (parsed.commandTokens.length === 0) {
9774
10659
  return { kind: "help", text: renderRootHelp(scope) };
@@ -9783,6 +10668,7 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9783
10668
  if (hasFlag(parsed.flags, "help")) {
9784
10669
  return { kind: "help", text: renderCommandHelp(scope, moduleName, commandName) };
9785
10670
  }
10671
+ const runtimeEnv = env ?? loadRuntimeEnv(scope);
9786
10672
  const command = findCommand(scope, moduleName, commandName);
9787
10673
  if (!command) {
9788
10674
  throw new CLIError("UNKNOWN_COMMAND", `unknown command: ${moduleName} ${commandName}`, 2);
@@ -9792,6 +10678,7 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9792
10678
  const fileQuery = loadQueryFromFlags(parsed.flags);
9793
10679
  const query = { ...scalarQuery ?? {}, ...fileQuery ?? {} };
9794
10680
  const body = loadBodyFromFlags(parsed.flags);
10681
+ let validatedBody = body;
9795
10682
  if (command.requestType) {
9796
10683
  if (body === void 0) {
9797
10684
  throw new CLIError("MISSING_BODY_FILE", `command requires --body-file for ${command.requestType}`, 2);
@@ -9811,10 +10698,13 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9811
10698
  path: issue.path.length > 0 ? `body.${issue.path.join(".")}` : "body",
9812
10699
  message: issue.message
9813
10700
  })),
9814
- tsHints: getTypeHints(command.requestType)
10701
+ tsHints: getTypeHints(command.requestType),
10702
+ docHints: getDocHints(command.requestType)
9815
10703
  }
9816
10704
  );
9817
10705
  }
10706
+ validatedBody = parsedBody.data;
10707
+ validateActionSpecificBody(scope, command, parsed.flags, validatedBody);
9818
10708
  } else {
9819
10709
  const unsupportedReason = getUnsupportedBodySchemaReason(command.requestType);
9820
10710
  if (unsupportedReason) {
@@ -9822,19 +10712,19 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9822
10712
  operation: `${scope}.${command.module}.${command.functionName}`,
9823
10713
  requestType: command.requestType,
9824
10714
  reason: unsupportedReason,
9825
- tsHints: getTypeHints(command.requestType)
10715
+ tsHints: getTypeHints(command.requestType),
10716
+ docHints: getDocHints(command.requestType)
9826
10717
  });
9827
10718
  }
9828
10719
  }
9829
10720
  }
9830
- const headers = buildRequestHeaders(env);
9831
- 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), {
9832
10722
  method: command.method,
9833
10723
  headers: {
9834
- ...headers,
10724
+ ...buildRequestHeaders(runtimeEnv),
9835
10725
  "Content-Type": "application/json"
9836
10726
  },
9837
- 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)
9838
10728
  });
9839
10729
  const raw = await response.text();
9840
10730
  let parsedResponse = raw;
@@ -9845,6 +10735,17 @@ async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl =
9845
10735
  if (!response.ok) {
9846
10736
  throw new CLIError("UPSTREAM_REQUEST_FAILED", typeof parsedResponse === "string" ? parsedResponse : JSON.stringify(parsedResponse), 1);
9847
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
+ }
9848
10749
  return {
9849
10750
  kind: "result",
9850
10751
  commandPath: command.commandPath,