@carthooks/arcubase-cli 0.1.19 → 0.1.20

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.
@@ -0,0 +1,205 @@
1
+ export type GeneratedHelpExample = {
2
+ title: string;
3
+ body?: unknown;
4
+ notes?: readonly string[];
5
+ };
6
+ export declare const helpExamplesIndex: {
7
+ readonly "admin.access-rule.assign-users": {
8
+ readonly command: readonly ["access-rule", "assign-users"];
9
+ readonly examples: readonly [{
10
+ readonly title: "replace user_scope with user, department, and actor scopes";
11
+ readonly body: {
12
+ readonly update: readonly ["user_scope"];
13
+ readonly options: {
14
+ readonly user_scope: readonly [{
15
+ readonly type: "user";
16
+ readonly id: 2188889901;
17
+ }, {
18
+ readonly type: "department";
19
+ readonly id: 2188881201;
20
+ }, {
21
+ readonly type: "actor";
22
+ readonly id: 2188883301;
23
+ }];
24
+ };
25
+ };
26
+ readonly notes: readonly ["id must be numeric arcubaseUserId, department ID, or actor ID", "assign-users updates user_scope only and preserves the existing policy"];
27
+ }];
28
+ };
29
+ readonly "admin.access-rule.create": {
30
+ readonly command: readonly ["access-rule", "create"];
31
+ readonly examples: readonly [{
32
+ readonly title: "full access for a specific arcubaseUserId";
33
+ readonly body: {
34
+ readonly name: "Admin full access";
35
+ readonly enabled: true;
36
+ readonly type: "form";
37
+ readonly options: {
38
+ readonly user_scope: readonly [{
39
+ readonly type: "user";
40
+ readonly id: 2188889977;
41
+ }];
42
+ readonly policy: {
43
+ readonly key: "custom";
44
+ readonly actions: readonly ["view", "add", "edit", "delete"];
45
+ readonly all_fields_read: true;
46
+ readonly all_fields_write: true;
47
+ };
48
+ readonly list_options: {};
49
+ };
50
+ };
51
+ }, {
52
+ readonly title: "department can view/add/edit only rows created by themselves";
53
+ readonly body: {
54
+ readonly name: "Sales own rows";
55
+ readonly enabled: true;
56
+ readonly type: "form";
57
+ readonly options: {
58
+ readonly user_scope: readonly [{
59
+ readonly type: "department";
60
+ readonly id: 2188881201;
61
+ }];
62
+ readonly policy: {
63
+ readonly key: "custom";
64
+ readonly actions: readonly ["view", "add", "edit"];
65
+ readonly all_fields_read: true;
66
+ readonly all_fields_write: true;
67
+ readonly condition: {
68
+ readonly mode: "and";
69
+ readonly conditions: readonly [{
70
+ readonly column: "creator";
71
+ readonly operator: "$eq";
72
+ readonly value: "[[current_user]]";
73
+ readonly value_from: 0;
74
+ readonly value_relation: "";
75
+ }];
76
+ };
77
+ };
78
+ readonly list_options: {};
79
+ };
80
+ };
81
+ readonly notes: readonly ["department scope includes child departments", "row-owner isolation uses [[current_user]] on creator"];
82
+ }, {
83
+ readonly title: "role actor can view rows matching a complex AND/OR condition";
84
+ readonly body: {
85
+ readonly name: "Sales manager review queue";
86
+ readonly enabled: true;
87
+ readonly type: "form";
88
+ readonly options: {
89
+ readonly user_scope: readonly [{
90
+ readonly type: "actor";
91
+ readonly id: 2188883301;
92
+ }];
93
+ readonly policy: {
94
+ readonly key: "custom";
95
+ readonly actions: readonly ["view", "edit"];
96
+ readonly all_fields_read: true;
97
+ readonly all_fields_write: true;
98
+ readonly condition: {
99
+ readonly mode: "and";
100
+ readonly conditions: readonly [{
101
+ readonly column: ":1004";
102
+ readonly operator: "$eq";
103
+ readonly value: "pending";
104
+ readonly value_from: 0;
105
+ readonly value_relation: "";
106
+ }, {
107
+ readonly column: "";
108
+ readonly operator: "";
109
+ readonly value: null;
110
+ readonly value_from: 0;
111
+ readonly value_relation: "";
112
+ readonly subset: {
113
+ readonly mode: "or";
114
+ readonly conditions: readonly [{
115
+ readonly column: "creator";
116
+ readonly operator: "$eq";
117
+ readonly value: "[[current_user]]";
118
+ readonly value_from: 0;
119
+ readonly value_relation: "";
120
+ }, {
121
+ readonly column: ":1005";
122
+ readonly operator: "$eq";
123
+ readonly value: "high";
124
+ readonly value_from: 0;
125
+ readonly value_relation: "";
126
+ }];
127
+ };
128
+ }];
129
+ };
130
+ };
131
+ readonly list_options: {};
132
+ };
133
+ };
134
+ readonly notes: readonly ["actor means Arcubase role id", "condition mode \"and\" and \"or\" are canonical; legacy \"all\" also reads as AND", "nested OR uses subset and leaves the wrapper column/operator empty"];
135
+ }];
136
+ };
137
+ readonly "user.row.bulk-update": {
138
+ readonly command: readonly ["row", "bulk-update"];
139
+ readonly examples: readonly [{
140
+ readonly title: "bulk update explicit row ids";
141
+ readonly body: {
142
+ readonly selection: {
143
+ readonly type: "ids";
144
+ readonly ids: readonly [2188890411, 2188890412];
145
+ readonly length: 2;
146
+ };
147
+ readonly fields: readonly [{
148
+ readonly id: 1003;
149
+ readonly action: {
150
+ readonly type: "set";
151
+ readonly value: 2;
152
+ };
153
+ }];
154
+ };
155
+ }, {
156
+ readonly title: "bulk update rows selected by a search condition";
157
+ readonly body: {
158
+ readonly selection: {
159
+ readonly type: "condition";
160
+ readonly condition: {
161
+ readonly selectAll: true;
162
+ readonly q: "SO-1001";
163
+ };
164
+ readonly length: 0;
165
+ };
166
+ readonly fields: readonly [{
167
+ readonly id: 1003;
168
+ readonly action: {
169
+ readonly type: "set";
170
+ readonly value: 2;
171
+ };
172
+ }];
173
+ };
174
+ readonly notes: readonly ["condition selection uses row-query style keys such as q, tab, and filter_:1002"];
175
+ }];
176
+ };
177
+ readonly "user.row.selection-action": {
178
+ readonly command: readonly ["row", "selection-action"];
179
+ readonly examples: readonly [{
180
+ readonly title: "run a custom action against explicit row ids";
181
+ readonly body: {
182
+ readonly selection: {
183
+ readonly type: "ids";
184
+ readonly ids: readonly [2188890411];
185
+ readonly length: 1;
186
+ };
187
+ };
188
+ readonly notes: readonly ["pass the backend action code with --action", "for query action, use ids or all selection instead of condition selection"];
189
+ }, {
190
+ readonly title: "run a custom action against a filtered selection";
191
+ readonly body: {
192
+ readonly selection: {
193
+ readonly type: "condition";
194
+ readonly condition: {
195
+ readonly selectAll: true;
196
+ readonly q: "SO-1001";
197
+ };
198
+ readonly length: 0;
199
+ };
200
+ };
201
+ readonly notes: readonly ["condition selection uses row-query style keys such as q, tab, and filter_:1002"];
202
+ }];
203
+ };
204
+ };
205
+ //# sourceMappingURL=help_examples.generated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help_examples.generated.d.ts","sourceRoot":"","sources":["../../src/generated/help_examples.generated.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwRgF,CAAA"}
@@ -0,0 +1,282 @@
1
+ // Generated by scripts/generate-help-examples.mjs. Do not edit by hand.
2
+ export const helpExamplesIndex = {
3
+ "admin.access-rule.assign-users": {
4
+ "command": [
5
+ "access-rule",
6
+ "assign-users"
7
+ ],
8
+ "examples": [
9
+ {
10
+ "title": "replace user_scope with user, department, and actor scopes",
11
+ "body": {
12
+ "update": [
13
+ "user_scope"
14
+ ],
15
+ "options": {
16
+ "user_scope": [
17
+ {
18
+ "type": "user",
19
+ "id": 2188889901
20
+ },
21
+ {
22
+ "type": "department",
23
+ "id": 2188881201
24
+ },
25
+ {
26
+ "type": "actor",
27
+ "id": 2188883301
28
+ }
29
+ ]
30
+ }
31
+ },
32
+ "notes": [
33
+ "id must be numeric arcubaseUserId, department ID, or actor ID",
34
+ "assign-users updates user_scope only and preserves the existing policy"
35
+ ]
36
+ }
37
+ ]
38
+ },
39
+ "admin.access-rule.create": {
40
+ "command": [
41
+ "access-rule",
42
+ "create"
43
+ ],
44
+ "examples": [
45
+ {
46
+ "title": "full access for a specific arcubaseUserId",
47
+ "body": {
48
+ "name": "Admin full access",
49
+ "enabled": true,
50
+ "type": "form",
51
+ "options": {
52
+ "user_scope": [
53
+ {
54
+ "type": "user",
55
+ "id": 2188889977
56
+ }
57
+ ],
58
+ "policy": {
59
+ "key": "custom",
60
+ "actions": [
61
+ "view",
62
+ "add",
63
+ "edit",
64
+ "delete"
65
+ ],
66
+ "all_fields_read": true,
67
+ "all_fields_write": true
68
+ },
69
+ "list_options": {}
70
+ }
71
+ }
72
+ },
73
+ {
74
+ "title": "department can view/add/edit only rows created by themselves",
75
+ "body": {
76
+ "name": "Sales own rows",
77
+ "enabled": true,
78
+ "type": "form",
79
+ "options": {
80
+ "user_scope": [
81
+ {
82
+ "type": "department",
83
+ "id": 2188881201
84
+ }
85
+ ],
86
+ "policy": {
87
+ "key": "custom",
88
+ "actions": [
89
+ "view",
90
+ "add",
91
+ "edit"
92
+ ],
93
+ "all_fields_read": true,
94
+ "all_fields_write": true,
95
+ "condition": {
96
+ "mode": "and",
97
+ "conditions": [
98
+ {
99
+ "column": "creator",
100
+ "operator": "$eq",
101
+ "value": "[[current_user]]",
102
+ "value_from": 0,
103
+ "value_relation": ""
104
+ }
105
+ ]
106
+ }
107
+ },
108
+ "list_options": {}
109
+ }
110
+ },
111
+ "notes": [
112
+ "department scope includes child departments",
113
+ "row-owner isolation uses [[current_user]] on creator"
114
+ ]
115
+ },
116
+ {
117
+ "title": "role actor can view rows matching a complex AND/OR condition",
118
+ "body": {
119
+ "name": "Sales manager review queue",
120
+ "enabled": true,
121
+ "type": "form",
122
+ "options": {
123
+ "user_scope": [
124
+ {
125
+ "type": "actor",
126
+ "id": 2188883301
127
+ }
128
+ ],
129
+ "policy": {
130
+ "key": "custom",
131
+ "actions": [
132
+ "view",
133
+ "edit"
134
+ ],
135
+ "all_fields_read": true,
136
+ "all_fields_write": true,
137
+ "condition": {
138
+ "mode": "and",
139
+ "conditions": [
140
+ {
141
+ "column": ":1004",
142
+ "operator": "$eq",
143
+ "value": "pending",
144
+ "value_from": 0,
145
+ "value_relation": ""
146
+ },
147
+ {
148
+ "column": "",
149
+ "operator": "",
150
+ "value": null,
151
+ "value_from": 0,
152
+ "value_relation": "",
153
+ "subset": {
154
+ "mode": "or",
155
+ "conditions": [
156
+ {
157
+ "column": "creator",
158
+ "operator": "$eq",
159
+ "value": "[[current_user]]",
160
+ "value_from": 0,
161
+ "value_relation": ""
162
+ },
163
+ {
164
+ "column": ":1005",
165
+ "operator": "$eq",
166
+ "value": "high",
167
+ "value_from": 0,
168
+ "value_relation": ""
169
+ }
170
+ ]
171
+ }
172
+ }
173
+ ]
174
+ }
175
+ },
176
+ "list_options": {}
177
+ }
178
+ },
179
+ "notes": [
180
+ "actor means Arcubase role id",
181
+ "condition mode \"and\" and \"or\" are canonical; legacy \"all\" also reads as AND",
182
+ "nested OR uses subset and leaves the wrapper column/operator empty"
183
+ ]
184
+ }
185
+ ]
186
+ },
187
+ "user.row.bulk-update": {
188
+ "command": [
189
+ "row",
190
+ "bulk-update"
191
+ ],
192
+ "examples": [
193
+ {
194
+ "title": "bulk update explicit row ids",
195
+ "body": {
196
+ "selection": {
197
+ "type": "ids",
198
+ "ids": [
199
+ 2188890411,
200
+ 2188890412
201
+ ],
202
+ "length": 2
203
+ },
204
+ "fields": [
205
+ {
206
+ "id": 1003,
207
+ "action": {
208
+ "type": "set",
209
+ "value": 2
210
+ }
211
+ }
212
+ ]
213
+ }
214
+ },
215
+ {
216
+ "title": "bulk update rows selected by a search condition",
217
+ "body": {
218
+ "selection": {
219
+ "type": "condition",
220
+ "condition": {
221
+ "selectAll": true,
222
+ "q": "SO-1001"
223
+ },
224
+ "length": 0
225
+ },
226
+ "fields": [
227
+ {
228
+ "id": 1003,
229
+ "action": {
230
+ "type": "set",
231
+ "value": 2
232
+ }
233
+ }
234
+ ]
235
+ },
236
+ "notes": [
237
+ "condition selection uses row-query style keys such as q, tab, and filter_:1002"
238
+ ]
239
+ }
240
+ ]
241
+ },
242
+ "user.row.selection-action": {
243
+ "command": [
244
+ "row",
245
+ "selection-action"
246
+ ],
247
+ "examples": [
248
+ {
249
+ "title": "run a custom action against explicit row ids",
250
+ "body": {
251
+ "selection": {
252
+ "type": "ids",
253
+ "ids": [
254
+ 2188890411
255
+ ],
256
+ "length": 1
257
+ }
258
+ },
259
+ "notes": [
260
+ "pass the backend action code with --action",
261
+ "for query action, use ids or all selection instead of condition selection"
262
+ ]
263
+ },
264
+ {
265
+ "title": "run a custom action against a filtered selection",
266
+ "body": {
267
+ "selection": {
268
+ "type": "condition",
269
+ "condition": {
270
+ "selectAll": true,
271
+ "q": "SO-1001"
272
+ },
273
+ "length": 0
274
+ }
275
+ },
276
+ "notes": [
277
+ "condition selection uses row-query style keys such as q, tab, and filter_:1002"
278
+ ]
279
+ }
280
+ ]
281
+ }
282
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAOhJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAc1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AAOD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAMlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA6HpI;AA8vDD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CA8MrI"}
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAQhJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAc1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AA8BD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAUlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA8HpI;AA8xDD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CA+NrI"}
@@ -10,6 +10,7 @@ import { getBodySchema, getCommandDocHints, getDocHints, getTypeHints, getUnsupp
10
10
  import { resolveArcubaseSDKPath } from './paths.js';
11
11
  import { compileCSVImportMapping, compileExcelImportMapping } from './entity_import_mapping.js';
12
12
  import { uploadLocalFileWithToken } from './local_upload.js';
13
+ import { renderCommandHelpExamples } from './help_examples.js';
13
14
  export function renderRootHelp(scope) {
14
15
  const binary = scope === 'admin' ? 'arcubase-admin' : 'arcubase';
15
16
  const items = listModules(scope).map((item) => ` - ${item}`);
@@ -50,9 +51,29 @@ function buildUnknownCommandDetails(scope, moduleName, commandName) {
50
51
  const suggestions = findCommandSuggestions(moduleName, commandName).map((item) => `${item.binary} ${item.moduleName}${item.commandName ? ` ${item.commandName}` : ''}`);
51
52
  return suggestions.length > 0 ? { suggestions } : undefined;
52
53
  }
54
+ function throwHelpExamplesRequiresCommand(scope, moduleName) {
55
+ const binary = binaryForScope(scope);
56
+ const suggestions = scope === 'admin'
57
+ ? [
58
+ `${binary} access-rule create --help-examples`,
59
+ `${binary} access-rule assign-users --help-examples`,
60
+ ]
61
+ : [
62
+ `${binary} row bulk-update --help-examples`,
63
+ `${binary} row selection-action --help-examples`,
64
+ ];
65
+ throw new CLIError('HELP_EXAMPLES_REQUIRES_COMMAND', '--help-examples must follow a final command', 2, {
66
+ operation: moduleName ? `${binary} ${moduleName} --help-examples` : `${binary} --help-examples`,
67
+ hint: `retry with a final command, for example: ${suggestions[0]}`,
68
+ suggestions,
69
+ });
70
+ }
53
71
  function sdkPath(file, env = process.env) {
54
72
  return resolveArcubaseSDKPath(file, env);
55
73
  }
74
+ function binaryForScope(scope) {
75
+ return scope === 'admin' ? 'arcubase-admin' : 'arcubase';
76
+ }
56
77
  export function renderCommandHelp(scope, moduleName, commandName, env = process.env) {
57
78
  const command = findCommand(scope, moduleName, commandName);
58
79
  if (!command) {
@@ -75,6 +96,7 @@ export function renderCommandHelp(scope, moduleName, commandName, env = process.
75
96
  command.requestType ? `body: ${bodyTypeText} via --body-json <json-string> | --body-file <file>.json` : 'body: none',
76
97
  queryFlags.length ? `query flags: ${queryFlags.join(', ')}, --query-file` : 'query flags: --query-file',
77
98
  pathFlags.length ? `path flags: ${pathFlags.join(', ')}` : 'path flags: none',
99
+ `copyable examples: ${scope === 'admin' ? 'arcubase-admin' : 'arcubase'} ${command.commandPath.join(' ')} --help-examples`,
78
100
  ...(isTableCreate
79
101
  ? [
80
102
  'body-json example:',
@@ -229,7 +251,7 @@ function buildScalarQuery(command, flags) {
229
251
  return Object.keys(out).length > 0 ? out : undefined;
230
252
  }
231
253
  function validateKnownFlags(command, flags, env = process.env) {
232
- const allowed = new Set(['help', 'body-file', 'body-json', 'query-file']);
254
+ const allowed = new Set(['help', 'help-examples', 'body-file', 'body-json', 'query-file']);
233
255
  for (const mapping of command.pathParams) {
234
256
  if (!getFixedValue(mapping)) {
235
257
  allowed.add(mapping.flag);
@@ -914,6 +936,32 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
914
936
  }
915
937
  }
916
938
  }
939
+ function normalizeNumericAccessRuleUserScopeIDs(scope, command, body) {
940
+ if (!isAccessRuleCommand(scope, command) || !isRecord(body) || !isRecord(body.options) || !Array.isArray(body.options.user_scope)) {
941
+ return body;
942
+ }
943
+ let changed = false;
944
+ const userScope = body.options.user_scope.map((item) => {
945
+ if (!isRecord(item) || typeof item.id !== 'string' || !/^\d+$/.test(item.id)) {
946
+ return item;
947
+ }
948
+ const id = Number(item.id);
949
+ if (!Number.isFinite(id) || !Number.isInteger(id)) {
950
+ return item;
951
+ }
952
+ changed = true;
953
+ return { ...item, id };
954
+ });
955
+ if (!changed)
956
+ return body;
957
+ return {
958
+ ...body,
959
+ options: {
960
+ ...body.options,
961
+ user_scope: userScope,
962
+ },
963
+ };
964
+ }
917
965
  function requireUpdateContains(scope, command, body, field, env) {
918
966
  if (!(field in body))
919
967
  return;
@@ -1639,16 +1687,32 @@ export async function executeCLI(scope, argv, env, fetchImpl = fetch) {
1639
1687
  const parsed = parseCLIArgs(argv);
1640
1688
  const envInput = env ?? process.env;
1641
1689
  if (parsed.commandTokens.length === 0) {
1690
+ if (hasFlag(parsed.flags, 'help-examples')) {
1691
+ throwHelpExamplesRequiresCommand(scope);
1692
+ }
1642
1693
  return { kind: 'help', text: renderRootHelp(scope) };
1643
1694
  }
1644
1695
  const [moduleName, commandName] = parsed.commandTokens;
1645
1696
  if (!moduleName) {
1697
+ if (hasFlag(parsed.flags, 'help-examples')) {
1698
+ throwHelpExamplesRequiresCommand(scope);
1699
+ }
1646
1700
  return { kind: 'help', text: renderRootHelp(scope) };
1647
1701
  }
1648
1702
  const singleTokenCommand = !commandName ? findCommand(scope, moduleName) : null;
1649
1703
  if (!commandName && !singleTokenCommand) {
1704
+ if (hasFlag(parsed.flags, 'help-examples')) {
1705
+ throwHelpExamplesRequiresCommand(scope, moduleName);
1706
+ }
1650
1707
  return { kind: 'help', text: renderModuleHelp(scope, moduleName, envInput) };
1651
1708
  }
1709
+ if (hasFlag(parsed.flags, 'help-examples')) {
1710
+ const command = commandName ? findCommand(scope, moduleName, commandName) : singleTokenCommand;
1711
+ if (!command) {
1712
+ throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName}${commandName ? ` ${commandName}` : ''}`, 2, buildUnknownCommandDetails(scope, moduleName, commandName ?? ''));
1713
+ }
1714
+ return { kind: 'help', text: renderCommandHelpExamples(scope, command) };
1715
+ }
1652
1716
  if (hasFlag(parsed.flags, 'help')) {
1653
1717
  return { kind: 'help', text: renderCommandHelp(scope, moduleName, commandName, envInput) };
1654
1718
  }
@@ -1689,6 +1753,7 @@ export async function executeCLI(scope, argv, env, fetchImpl = fetch) {
1689
1753
  if (body === undefined) {
1690
1754
  throw new CLIError('MISSING_BODY_FILE', `command requires --body-json or --body-file for ${command.requestType}; prefer --body-json to avoid file creation`, 2);
1691
1755
  }
1756
+ body = normalizeNumericAccessRuleUserScopeIDs(scope, command, body);
1692
1757
  if (isTableCreateCommand(scope, command)) {
1693
1758
  requireTableCreateSchemaBody(scope, command, body, runtimeEnv);
1694
1759
  validateActionSpecificRawBody(scope, command, body, runtimeEnv);
@@ -0,0 +1,10 @@
1
+ import type { CommandDef, CommandScope } from './command_registry.js';
2
+ type HelpExample = {
3
+ title: string;
4
+ body?: unknown;
5
+ notes?: readonly string[];
6
+ };
7
+ export declare function getCommandHelpExamples(scope: CommandScope, command: CommandDef): readonly HelpExample[];
8
+ export declare function renderCommandHelpExamples(scope: CommandScope, command: CommandDef): string;
9
+ export {};
10
+ //# sourceMappingURL=help_examples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help_examples.d.ts","sourceRoot":"","sources":["../../src/runtime/help_examples.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAErE,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAyBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,GAAG,SAAS,WAAW,EAAE,CAEvG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAwB1F"}