@carthooks/arcubase-cli 0.1.12 → 0.1.15
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.
- package/bundle/arcubase-admin.mjs +15019 -3802
- package/bundle/arcubase.mjs +15019 -3802
- package/dist/generated/command_registry.generated.d.ts +108 -0
- package/dist/generated/command_registry.generated.d.ts.map +1 -1
- package/dist/generated/command_registry.generated.js +145 -0
- package/dist/generated/zod_registry.generated.d.ts +23 -23
- package/dist/runtime/entity_import_mapping.d.ts +12 -0
- package/dist/runtime/entity_import_mapping.d.ts.map +1 -0
- package/dist/runtime/entity_import_mapping.js +133 -0
- package/dist/runtime/entity_save_schema.d.ts.map +1 -1
- package/dist/runtime/entity_save_schema.js +23 -2
- package/dist/runtime/errors.d.ts +1 -0
- package/dist/runtime/errors.d.ts.map +1 -1
- package/dist/runtime/execute.d.ts.map +1 -1
- package/dist/runtime/execute.js +414 -8
- package/dist/runtime/local_upload.d.ts +10 -0
- package/dist/runtime/local_upload.d.ts.map +1 -0
- package/dist/runtime/local_upload.js +73 -0
- package/dist/tests/entity_save_schema.test.js +38 -0
- package/dist/tests/execute_validation.test.js +64 -2
- package/dist/tests/help.test.js +2 -0
- package/package.json +7 -7
- package/sdk-dist/docs/runtime-reference/README.md +4 -0
- package/sdk-dist/docs/runtime-reference/access-rule.md +19 -0
- package/sdk-dist/docs/runtime-reference/entity-schema/textarea.md +2 -2
- package/sdk-dist/docs/runtime-reference/examples/crm-01/lead.query.json +1 -1
- package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.query.json +1 -1
- package/sdk-dist/docs/runtime-reference/examples/wms-01/inventory-snapshot.query.json +1 -1
- package/sdk-dist/docs/runtime-reference/row-crud.md +68 -0
- package/sdk-dist/docs/runtime-reference/search-and-bulk-actions.md +26 -1
- package/sdk-dist/docs/runtime-reference/table-lifecycle.md +1 -1
- package/sdk-dist/generated/command_registry.generated.ts +145 -0
- package/sdk-dist/types/common.ts +1 -0
- package/src/generated/command_registry.generated.ts +145 -0
- package/src/runtime/entity_import_mapping.ts +172 -0
- package/src/runtime/entity_save_schema.ts +27 -3
- package/src/runtime/errors.ts +1 -0
- package/src/runtime/execute.ts +434 -10
- package/src/runtime/local_upload.ts +84 -0
- package/src/tests/command_registry.test.ts +4 -0
- package/src/tests/entity_import_mapping.test.ts +87 -0
- package/src/tests/entity_save_schema.test.ts +40 -0
- package/src/tests/execute_validation.test.ts +299 -5
- package/src/tests/help.test.ts +16 -0
- package/src/tests/local_upload.test.ts +47 -0
- package/src/tests/zod_registry.test.ts +27 -0
|
@@ -61,6 +61,44 @@ test('EntitySaveReqVO normalizes mechanical FieldVO defaults', () => {
|
|
|
61
61
|
assert.equal(parsed.data.fields[0].transfers, null);
|
|
62
62
|
assert.deepEqual(parsed.data.fields[0].depends, []);
|
|
63
63
|
});
|
|
64
|
+
test('EntitySaveReqVO rejects textarea size as string', () => {
|
|
65
|
+
assert.ok(schema);
|
|
66
|
+
const parsed = schema.safeParse({
|
|
67
|
+
name: '订单',
|
|
68
|
+
field_id_seq: 1003,
|
|
69
|
+
layout: [[1001], [1002]],
|
|
70
|
+
fields: [
|
|
71
|
+
buildMinimalField(1001),
|
|
72
|
+
{
|
|
73
|
+
...buildMinimalField(1002),
|
|
74
|
+
label: '描述',
|
|
75
|
+
type: 'textarea',
|
|
76
|
+
key: 'description',
|
|
77
|
+
options: { placeholder: '', html: false, size: 'default', lengthLimit: false, lengthMin: 0, lengthMax: 2000 },
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
assert.equal(parsed.success, false);
|
|
82
|
+
});
|
|
83
|
+
test('EntitySaveReqVO accepts textarea size as number', () => {
|
|
84
|
+
assert.ok(schema);
|
|
85
|
+
const parsed = schema.safeParse({
|
|
86
|
+
name: '订单',
|
|
87
|
+
field_id_seq: 1003,
|
|
88
|
+
layout: [[1001], [1002]],
|
|
89
|
+
fields: [
|
|
90
|
+
buildMinimalField(1001),
|
|
91
|
+
{
|
|
92
|
+
...buildMinimalField(1002),
|
|
93
|
+
label: '描述',
|
|
94
|
+
type: 'textarea',
|
|
95
|
+
key: 'description',
|
|
96
|
+
options: { placeholder: '', html: false, size: 6, lengthLimit: false, lengthMin: 0, lengthMax: 2000 },
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
assert.equal(parsed.success, true);
|
|
101
|
+
});
|
|
64
102
|
test('EntitySaveReqVO rejects fields as object', () => {
|
|
65
103
|
assert.ok(schema);
|
|
66
104
|
const parsed = schema.safeParse({
|
|
@@ -250,6 +250,37 @@ test('body json parse errors include command docs and type hints', async () => {
|
|
|
250
250
|
return true;
|
|
251
251
|
});
|
|
252
252
|
});
|
|
253
|
+
test('access-rule invalid json returns copyable create retry examples', async () => {
|
|
254
|
+
await assert.rejects(async () => {
|
|
255
|
+
await executeCLI('admin', ['access-rule', 'create', '--app-id', 'app_1', '--table-id', 'table_1', '--body-json', '{"name":"Admin full access","enabled":true,"type":"form","options":{"user_scope":[{"type":"user","id":2188889977}],"policy":{"key":"custom","actions":["view","add","edit","delete"],"all_fields_read":true,"all_fields_write":true},"list_options":{}}'], env, async () => new Response('{}', { status: 200 }));
|
|
256
|
+
}, (error) => {
|
|
257
|
+
assert.ok(error instanceof CLIError);
|
|
258
|
+
assert.equal(error.code, 'INVALID_BODY_JSON');
|
|
259
|
+
assert.equal(error.details?.requestType, 'AppIngressCreateReqVO');
|
|
260
|
+
assert.match(error.message, /retryToolCalls/);
|
|
261
|
+
const toolCall = (error.details?.retryToolCalls ?? [])[0];
|
|
262
|
+
assert.ok(toolCall);
|
|
263
|
+
assert.equal(toolCall.command, 'access-rule create');
|
|
264
|
+
assert.deepEqual(toolCall.args.slice(0, 5), ['--app-id', '<app_id>', '--table-id', '<table_id>', '--body-json']);
|
|
265
|
+
const body = JSON.parse(toolCall.args[5]);
|
|
266
|
+
assert.deepEqual(body, {
|
|
267
|
+
name: 'Admin full access',
|
|
268
|
+
enabled: true,
|
|
269
|
+
type: 'form',
|
|
270
|
+
options: {
|
|
271
|
+
user_scope: [{ type: 'user', id: 2188889977 }],
|
|
272
|
+
policy: {
|
|
273
|
+
key: 'custom',
|
|
274
|
+
actions: ['view', 'add', 'edit', 'delete'],
|
|
275
|
+
all_fields_read: true,
|
|
276
|
+
all_fields_write: true,
|
|
277
|
+
},
|
|
278
|
+
list_options: {},
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
return true;
|
|
282
|
+
});
|
|
283
|
+
});
|
|
253
284
|
test('access-rule list executes against external root path', async () => {
|
|
254
285
|
const out = await executeCLI('admin', ['access-rule', 'list', '--app-id', 'app_1', '--table-id', 'table_1'], env, async (url, init) => new Response(JSON.stringify({ url, method: init?.method }), { status: 200 }));
|
|
255
286
|
assert.equal(out.kind, 'result');
|
|
@@ -306,7 +337,7 @@ test('table update-schema rejects per-user permission patches', async () => {
|
|
|
306
337
|
layout: [[1001], [1002]],
|
|
307
338
|
fields: [
|
|
308
339
|
{ id: 1001, label: 'Title', type: 'text', required: true, unique: false, editable: true, visible: true, show_label: true, scannable: false, default_value_mode: 0, description: '', value: null, number_decimal: 0, depends: [], key: 'title', code_index: false, options: { type: 'text', placeholder: '', lengthLimit: false, lengthMin: 0, lengthMax: 255 }, transfers: null, children: null },
|
|
309
|
-
{ id: 1002, label: 'Description', type: 'textarea', required: false, unique: false, editable: true, visible: true, show_label: true, scannable: false, default_value_mode: 0, description: '', value: null, number_decimal: 0, depends: [], key: 'description', code_index: false, options: { placeholder: '', html: false, size:
|
|
340
|
+
{ id: 1002, label: 'Description', type: 'textarea', required: false, unique: false, editable: true, visible: true, show_label: true, scannable: false, default_value_mode: 0, description: '', value: null, number_decimal: 0, depends: [], key: 'description', code_index: false, options: { placeholder: '', html: false, size: 6, lengthLimit: false, lengthMin: 0, lengthMax: 2000 }, transfers: null, children: null, permission: { user: { read: false } } },
|
|
310
341
|
],
|
|
311
342
|
options: { Buttons: [], CustomActions: [], FrontendEvents: [], TitleFormat: { Fields: [], Parts: [], Body: '' }, misc: {} },
|
|
312
343
|
workflow_enabled: false,
|
|
@@ -396,6 +427,37 @@ test('row get resolves internal policy_id as query parameter', async () => {
|
|
|
396
427
|
assert.equal(out.kind, 'result');
|
|
397
428
|
assert.equal(calls[0], 'https://arcubase.example.com/api/entity/2188900691/2188900694/row/4000000046?policy_id=policy_hash_1');
|
|
398
429
|
});
|
|
430
|
+
test('row get returns machine-readable row value evidence', async () => {
|
|
431
|
+
const out = await executeCLI('user', ['row', 'get', '--app-id', '2188900691', '--table-id', '2188900694', '--row-id', '4000000046'], env, withRowPolicyResolver('2188900694', ['view'], async () => new Response(JSON.stringify({
|
|
432
|
+
data: {
|
|
433
|
+
record: {
|
|
434
|
+
id: 4000000046,
|
|
435
|
+
fields: { 1001: '复测投票' },
|
|
436
|
+
},
|
|
437
|
+
fieldPermits: {
|
|
438
|
+
all_fields_read: false,
|
|
439
|
+
fields: [
|
|
440
|
+
{ key: ':1001', read: true, write: true, report: false },
|
|
441
|
+
{ key: ':1002', read: false, write: false, report: false },
|
|
442
|
+
{ key: ':1003', read: true, write: true, report: false },
|
|
443
|
+
],
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
}), { status: 200 })));
|
|
447
|
+
assert.deepEqual(out.rowValueEvidence, {
|
|
448
|
+
source: 'row get record.fields',
|
|
449
|
+
returnedFieldIds: ['1001'],
|
|
450
|
+
notReturnedFieldIds: ['1002', '1003'],
|
|
451
|
+
deniedReadFieldIds: ['1002'],
|
|
452
|
+
absentFieldMeaning: 'not returned to current user; no row-value evidence',
|
|
453
|
+
rules: [
|
|
454
|
+
'current row values come only from row query fields or row get record.fields',
|
|
455
|
+
'table schema fields[].value and default_value_mode are schema defaults, not returned row values',
|
|
456
|
+
'a field id absent from returned row fields has no row-value evidence',
|
|
457
|
+
'read visibility status is fieldPermits read:false; FIELD_PERMISSION_REQUIRED is only a write preflight error',
|
|
458
|
+
],
|
|
459
|
+
});
|
|
460
|
+
});
|
|
399
461
|
test('row command rejects user-provided policy_id', async () => {
|
|
400
462
|
const bodyFile = tempJSONFile({ fields: { 1001: '今天吃什么' }, policy_id: 'manual_policy' });
|
|
401
463
|
await assert.rejects(async () => {
|
|
@@ -562,7 +624,7 @@ test('row query unknown limit flag gives body-json retry path', async () => {
|
|
|
562
624
|
assert.ok(error instanceof CLIError);
|
|
563
625
|
assert.equal(error.code, 'UNKNOWN_FLAG');
|
|
564
626
|
assert.equal(error.details?.requestType, 'EntityQueryReqVO');
|
|
565
|
-
assert.deepEqual(error.details?.shapeHint, { limit: 20, offset: 0, search: {
|
|
627
|
+
assert.deepEqual(error.details?.shapeHint, { limit: 20, offset: 0, search: { q: 'SO-1001' }, sorts: [{ column: ':1001', order: 'asc' }] });
|
|
566
628
|
assert.ok(error.details?.suggestions?.some((item) => item.includes('--body-json')));
|
|
567
629
|
return true;
|
|
568
630
|
});
|
package/dist/tests/help.test.js
CHANGED
|
@@ -81,6 +81,8 @@ test('admin access-rule help gives update whitelist and assign-users body-json e
|
|
|
81
81
|
assert.equal(create.kind, 'help');
|
|
82
82
|
assert.match(create.text, /Access rule/);
|
|
83
83
|
assert.match(create.text, /access-rule\.md/);
|
|
84
|
+
assert.match(create.text, /full access/);
|
|
85
|
+
assert.match(create.text, /"actions":\["view","add","edit","delete"\]/);
|
|
84
86
|
assert.match(create.text, /"user_scope":\[\{"type":"user","id":2188889901\}\]/);
|
|
85
87
|
assert.doesNotMatch(create.text, /"user_scope":\[\{"type":"member"/);
|
|
86
88
|
const update = await executeCLI('admin', ['access-rule', 'update', '--help'], env, async () => new Response('{}'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carthooks/arcubase-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Arcubase runtime CLI for admin and user command execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@carthooks/client-ts": "0.8.0",
|
|
34
|
-
"zod": "^
|
|
34
|
+
"zod": "^4.4.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@types/node": "^
|
|
38
|
-
"esbuild": "^0.
|
|
39
|
-
"ts-morph": "^
|
|
40
|
-
"tsx": "^4.
|
|
41
|
-
"typescript": "^
|
|
37
|
+
"@types/node": "^25.9.2",
|
|
38
|
+
"esbuild": "^0.28.0",
|
|
39
|
+
"ts-morph": "^28.0.0",
|
|
40
|
+
"tsx": "^4.22.4",
|
|
41
|
+
"typescript": "^6.0.3"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -35,12 +35,16 @@ Common commands:
|
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
arcubase-admin app create --body-file create-app.json | --body-json <json-string>
|
|
38
|
+
arcubase-admin app create-from-bundle-url --url <bundle_url> [--name <app_name>]
|
|
39
|
+
arcubase-admin app watch-import-task --task-id <task_id> --ttl-seconds 300
|
|
38
40
|
arcubase-admin table create --app-id <app_id> --body-json <json-string> | --body-file table-create.json
|
|
39
41
|
arcubase-admin table get --app-id <app_id> --table-id <table_id>
|
|
40
42
|
arcubase-admin table update-schema --app-id <app_id> --table-id <table_id> --body-json <json-string> | --body-file table-schema.json
|
|
41
43
|
arcubase-admin access-rule assign-users --app-id <app_id> --table-id <table_id> --rule-id <rule_id> --body-json <json-string> | --body-file assign-users.json
|
|
42
44
|
```
|
|
43
45
|
|
|
46
|
+
`--ttl-seconds` is a local wait limit. It does not cancel the backend import task.
|
|
47
|
+
|
|
44
48
|
Use `arcubase` for:
|
|
45
49
|
|
|
46
50
|
- row insert
|
|
@@ -20,6 +20,14 @@ Use the numeric `tenantUserId` / `TenantUser.ID`.
|
|
|
20
20
|
Do not use hash ids such as `arcubaseTenantUserId`.
|
|
21
21
|
Use `user_scope[].type:"user"` for a tenant user. Do not use FieldVO field type `member` in access rules.
|
|
22
22
|
|
|
23
|
+
## Body Input
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
--body-json '<json-string>' | --body-file access-rule.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Prefer `--body-json` for short payloads. `--body-file` is available for large or fragile JSON payloads.
|
|
30
|
+
|
|
23
31
|
## Create Read/Write Rule With Hidden Field
|
|
24
32
|
|
|
25
33
|
```bash
|
|
@@ -29,6 +37,17 @@ arcubase-admin access-rule create \
|
|
|
29
37
|
--body-json '{"name":"Sales read write","enabled":true,"type":"form","options":{"user_scope":[{"type":"user","id":2188889901}],"policy":{"key":"custom","actions":["view","add","edit"],"all_fields_read":false,"all_fields_write":false,"fields":[{"key":":1001","read":true,"write":true,"report":false},{"key":":1002","read":false,"write":false,"report":false},{"key":":1003","read":true,"write":true,"report":false}]},"list_options":{}}}'
|
|
30
38
|
```
|
|
31
39
|
|
|
40
|
+
## Create Admin Full Access Rule
|
|
41
|
+
|
|
42
|
+
Use this for the operator's own admin entry before creating seed rows.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
arcubase-admin access-rule create \
|
|
46
|
+
--app-id 2188893436 \
|
|
47
|
+
--table-id 2188893443 \
|
|
48
|
+
--body-json '{"name":"Admin full access","enabled":true,"type":"form","options":{"user_scope":[{"type":"user","id":2188889977}],"policy":{"key":"custom","actions":["view","add","edit","delete"],"all_fields_read":true,"all_fields_write":true},"list_options":{}}}'
|
|
49
|
+
```
|
|
50
|
+
|
|
32
51
|
Rules:
|
|
33
52
|
|
|
34
53
|
- read permission = `actions:["view"]`
|
|
@@ -23,7 +23,7 @@ Multi-line text field.
|
|
|
23
23
|
"options": {
|
|
24
24
|
"placeholder": "",
|
|
25
25
|
"html": false,
|
|
26
|
-
"size":
|
|
26
|
+
"size": 6,
|
|
27
27
|
"lengthLimit": false,
|
|
28
28
|
"lengthMin": 0,
|
|
29
29
|
"lengthMax": 2000
|
|
@@ -44,4 +44,4 @@ Multi-line text field.
|
|
|
44
44
|
|
|
45
45
|
- `placeholder` matters only when `html=false`
|
|
46
46
|
- when `lengthLimit=true`, it is recommended to provide both `lengthMin` and `lengthMax`
|
|
47
|
-
-
|
|
47
|
+
- `size` is numeric and maps to editor rows; use `6` for the default two-row textarea
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"limit":20,"offset":0,"search":{"
|
|
1
|
+
{"limit":20,"offset":0,"search":{"q":"lead"},"sorts":[{"column":":1001","order":"asc"}]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"limit":20,"offset":0,"search":{"
|
|
1
|
+
{"limit":20,"offset":0,"search":{"q":"SKU-1001"},"sorts":[{"column":":1001","order":"desc"}]}
|
|
@@ -83,6 +83,12 @@ Typical row shape:
|
|
|
83
83
|
}
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
Returned values:
|
|
87
|
+
|
|
88
|
+
- current row values are only in `fields`
|
|
89
|
+
- fields absent from `fields` are not returned to the current user and have no row-value evidence
|
|
90
|
+
- table schema `fields[].value` and `default_value_mode` describe schema defaults, not current row values
|
|
91
|
+
|
|
86
92
|
## Read one row
|
|
87
93
|
|
|
88
94
|
Command:
|
|
@@ -96,6 +102,13 @@ arcubase row get \
|
|
|
96
102
|
|
|
97
103
|
Use this when you already know the row id and want the full record payload.
|
|
98
104
|
|
|
105
|
+
Returned values:
|
|
106
|
+
|
|
107
|
+
- current row values are in `record.fields`
|
|
108
|
+
- fields absent from `record.fields` are not returned to the current user and have no row-value evidence
|
|
109
|
+
- use `fieldPermits` only to explain access, not as current row values
|
|
110
|
+
- read visibility status is `fieldPermits read:false`; `FIELD_PERMISSION_REQUIRED` is a write preflight error from row create/update
|
|
111
|
+
|
|
99
112
|
## Update a row
|
|
100
113
|
|
|
101
114
|
Command:
|
|
@@ -139,6 +152,61 @@ Success result:
|
|
|
139
152
|
|
|
140
153
|
The update command returns `true`, not the updated row body.
|
|
141
154
|
|
|
155
|
+
## Import Records
|
|
156
|
+
|
|
157
|
+
Excel:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
arcubase row import-excel \
|
|
161
|
+
--app-id <app_id> \
|
|
162
|
+
--table-id <table_id> \
|
|
163
|
+
--file records.xlsx \
|
|
164
|
+
--mapping-file mapping.excel.json \
|
|
165
|
+
--ttl-seconds 300
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
CSV:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
arcubase row import-csv \
|
|
172
|
+
--app-id <app_id> \
|
|
173
|
+
--table-id <table_id> \
|
|
174
|
+
--file records.csv \
|
|
175
|
+
--mapping-file mapping.csv.json \
|
|
176
|
+
--ttl-seconds 300
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Both commands accept local file paths only. CSV mapping uses headers. Excel mapping uses column letters. The mapping file is validated locally before the import task is started.
|
|
180
|
+
|
|
181
|
+
Excel `mapping.excel.json`:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"sheet": "Sheet1",
|
|
186
|
+
"mode": "addonly",
|
|
187
|
+
"headerRow": 1,
|
|
188
|
+
"dataStartRow": 2,
|
|
189
|
+
"fields": [
|
|
190
|
+
{ "fieldId": 1001, "column": "A" }
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
CSV `mapping.csv.json`:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"mode": "addonly",
|
|
200
|
+
"header": true,
|
|
201
|
+
"dataStartRow": 2,
|
|
202
|
+
"fields": [
|
|
203
|
+
{ "fieldId": 1001, "header": "客户名称" }
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For `updateonly` and `addorupdate`, include `recordId` in the mapping. Use `arcubase-admin table get --app-id <app_id> --table-id <table_id>` to inspect numeric field ids.
|
|
209
|
+
|
|
142
210
|
## Delete rows
|
|
143
211
|
|
|
144
212
|
Command:
|
|
@@ -38,13 +38,38 @@ For extra query-string parameters, also use:
|
|
|
38
38
|
"limit": 20,
|
|
39
39
|
"offset": 0,
|
|
40
40
|
"search": {
|
|
41
|
-
"
|
|
41
|
+
"q": "ORD-3001"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
This is the current success path for free-text search.
|
|
47
47
|
|
|
48
|
+
Rules:
|
|
49
|
+
|
|
50
|
+
- `search` is route-query state, not `ConditionSet`
|
|
51
|
+
- every `search` value must be a string
|
|
52
|
+
- use `q` for free-text search
|
|
53
|
+
- use `tab` for a list tab id
|
|
54
|
+
- use `filter_:<field_id_or_prop>` for field filters
|
|
55
|
+
- do not use `search.conditions`, `search.condition`, `search.field_filters`, `filter`, `filters`, `where`, `order`, or `orderBy`
|
|
56
|
+
|
|
57
|
+
## Field filter
|
|
58
|
+
|
|
59
|
+
`query.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"limit": 20,
|
|
64
|
+
"offset": 0,
|
|
65
|
+
"search": {
|
|
66
|
+
"filter_:1002": "%7B%22is%22%3A%22member_1%22%7D"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`filter_:...` values are URL-encoded `FilterCond` JSON strings. For example, `%7B%22is%22%3A%22member_1%22%7D` decodes to `{"is":"member_1"}`.
|
|
72
|
+
|
|
48
73
|
## Sorts
|
|
49
74
|
|
|
50
75
|
`query.json`:
|
|
@@ -102,7 +102,7 @@ Minimal `table-create.json`:
|
|
|
102
102
|
"depends": [],
|
|
103
103
|
"key": "description",
|
|
104
104
|
"code_index": false,
|
|
105
|
-
"options": {"placeholder": "", "html": false, "size":
|
|
105
|
+
"options": {"placeholder": "", "html": false, "size": 6, "lengthLimit": false, "lengthMin": 0, "lengthMax": 2000},
|
|
106
106
|
"transfers": null,
|
|
107
107
|
"children": null
|
|
108
108
|
},
|
|
@@ -68,6 +68,63 @@ export const adminCommands = [
|
|
|
68
68
|
"queryParams": [],
|
|
69
69
|
"responseType": "AppCreateByTenantsRespVO"
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
"scope": "admin",
|
|
73
|
+
"module": "app",
|
|
74
|
+
"functionName": "createAppFromBundleURL",
|
|
75
|
+
"commandPath": [
|
|
76
|
+
"app",
|
|
77
|
+
"create-from-bundle-url"
|
|
78
|
+
],
|
|
79
|
+
"method": "POST",
|
|
80
|
+
"endpoint": "/api/apps/import-task",
|
|
81
|
+
"pathParams": [],
|
|
82
|
+
"controller": "manual",
|
|
83
|
+
"requestType": null,
|
|
84
|
+
"queryParams": [
|
|
85
|
+
{
|
|
86
|
+
"key": "url",
|
|
87
|
+
"flag": "url",
|
|
88
|
+
"type": "string",
|
|
89
|
+
"hasDefault": false
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"key": "name",
|
|
93
|
+
"flag": "name",
|
|
94
|
+
"type": "string",
|
|
95
|
+
"hasDefault": true
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"responseType": "AppBundleImportTaskCreateRespVO"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"scope": "admin",
|
|
102
|
+
"module": "app",
|
|
103
|
+
"functionName": "watchAppBundleImportTask",
|
|
104
|
+
"commandPath": [
|
|
105
|
+
"app",
|
|
106
|
+
"watch-import-task"
|
|
107
|
+
],
|
|
108
|
+
"method": "GET",
|
|
109
|
+
"endpoint": "/api/apps/import-task/:task_id",
|
|
110
|
+
"pathParams": [
|
|
111
|
+
{
|
|
112
|
+
"param": "task_id",
|
|
113
|
+
"flag": "task-id"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"controller": "manual",
|
|
117
|
+
"requestType": null,
|
|
118
|
+
"queryParams": [
|
|
119
|
+
{
|
|
120
|
+
"key": "ttl_seconds",
|
|
121
|
+
"flag": "ttl-seconds",
|
|
122
|
+
"type": "number",
|
|
123
|
+
"hasDefault": false
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"responseType": "AppBundleImportTaskStatusRespVO"
|
|
127
|
+
},
|
|
71
128
|
{
|
|
72
129
|
"scope": "admin",
|
|
73
130
|
"module": "app",
|
|
@@ -791,6 +848,94 @@ export const userCommands = [
|
|
|
791
848
|
"queryParams": [],
|
|
792
849
|
"responseType": "EntityBulkUpdateRespVO"
|
|
793
850
|
},
|
|
851
|
+
{
|
|
852
|
+
"scope": "user",
|
|
853
|
+
"module": "row",
|
|
854
|
+
"functionName": "importEntityRecordsFromExcel",
|
|
855
|
+
"commandPath": [
|
|
856
|
+
"row",
|
|
857
|
+
"import-excel"
|
|
858
|
+
],
|
|
859
|
+
"method": "POST",
|
|
860
|
+
"endpoint": "/api/entity/:app_id/:entity_id/import",
|
|
861
|
+
"pathParams": [
|
|
862
|
+
{
|
|
863
|
+
"param": "app_id",
|
|
864
|
+
"flag": "app-id"
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
"param": "entity_id",
|
|
868
|
+
"flag": "table-id"
|
|
869
|
+
}
|
|
870
|
+
],
|
|
871
|
+
"controller": "manual",
|
|
872
|
+
"requestType": null,
|
|
873
|
+
"queryParams": [
|
|
874
|
+
{
|
|
875
|
+
"key": "file",
|
|
876
|
+
"flag": "file",
|
|
877
|
+
"type": "string",
|
|
878
|
+
"hasDefault": false
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
"key": "mapping_file",
|
|
882
|
+
"flag": "mapping-file",
|
|
883
|
+
"type": "string",
|
|
884
|
+
"hasDefault": false
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
"key": "ttl_seconds",
|
|
888
|
+
"flag": "ttl-seconds",
|
|
889
|
+
"type": "number",
|
|
890
|
+
"hasDefault": true
|
|
891
|
+
}
|
|
892
|
+
],
|
|
893
|
+
"responseType": "ImporterGetStateRespVO"
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
"scope": "user",
|
|
897
|
+
"module": "row",
|
|
898
|
+
"functionName": "importEntityRecordsFromCSV",
|
|
899
|
+
"commandPath": [
|
|
900
|
+
"row",
|
|
901
|
+
"import-csv"
|
|
902
|
+
],
|
|
903
|
+
"method": "POST",
|
|
904
|
+
"endpoint": "/api/entity/:app_id/:entity_id/import",
|
|
905
|
+
"pathParams": [
|
|
906
|
+
{
|
|
907
|
+
"param": "app_id",
|
|
908
|
+
"flag": "app-id"
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
"param": "entity_id",
|
|
912
|
+
"flag": "table-id"
|
|
913
|
+
}
|
|
914
|
+
],
|
|
915
|
+
"controller": "manual",
|
|
916
|
+
"requestType": null,
|
|
917
|
+
"queryParams": [
|
|
918
|
+
{
|
|
919
|
+
"key": "file",
|
|
920
|
+
"flag": "file",
|
|
921
|
+
"type": "string",
|
|
922
|
+
"hasDefault": false
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
"key": "mapping_file",
|
|
926
|
+
"flag": "mapping-file",
|
|
927
|
+
"type": "string",
|
|
928
|
+
"hasDefault": false
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"key": "ttl_seconds",
|
|
932
|
+
"flag": "ttl-seconds",
|
|
933
|
+
"type": "number",
|
|
934
|
+
"hasDefault": true
|
|
935
|
+
}
|
|
936
|
+
],
|
|
937
|
+
"responseType": "ImporterGetStateRespVO"
|
|
938
|
+
},
|
|
794
939
|
{
|
|
795
940
|
"scope": "user",
|
|
796
941
|
"module": "row",
|
package/sdk-dist/types/common.ts
CHANGED