@carthooks/arcubase-cli 0.1.2 → 0.1.4

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 (106) hide show
  1. package/bundle/arcubase-admin.mjs +1238 -16
  2. package/bundle/arcubase.mjs +1238 -16
  3. package/dist/bin/arcubase-admin.js +0 -0
  4. package/dist/bin/arcubase.js +0 -0
  5. package/dist/runtime/command_registry.d.ts +8 -0
  6. package/dist/runtime/command_registry.d.ts.map +1 -1
  7. package/dist/runtime/command_registry.js +35 -0
  8. package/dist/runtime/entity_save_schema.d.ts +15 -0
  9. package/dist/runtime/entity_save_schema.d.ts.map +1 -0
  10. package/dist/runtime/entity_save_schema.js +641 -0
  11. package/dist/runtime/errors.d.ts +11 -0
  12. package/dist/runtime/errors.d.ts.map +1 -1
  13. package/dist/runtime/execute.d.ts.map +1 -1
  14. package/dist/runtime/execute.js +294 -12
  15. package/dist/runtime/upload.d.ts +13 -0
  16. package/dist/runtime/upload.d.ts.map +1 -0
  17. package/dist/runtime/upload.js +148 -0
  18. package/dist/runtime/zod_registry.d.ts +6 -0
  19. package/dist/runtime/zod_registry.d.ts.map +1 -1
  20. package/dist/runtime/zod_registry.js +136 -0
  21. package/dist/tests/command_registry.test.js +5 -0
  22. package/dist/tests/entity_save_schema.test.d.ts +2 -0
  23. package/dist/tests/entity_save_schema.test.d.ts.map +1 -0
  24. package/dist/tests/entity_save_schema.test.js +221 -0
  25. package/dist/tests/execute_validation.test.js +603 -0
  26. package/dist/tests/help.test.js +49 -0
  27. package/dist/tests/upload.test.d.ts +2 -0
  28. package/dist/tests/upload.test.d.ts.map +1 -0
  29. package/dist/tests/upload.test.js +107 -0
  30. package/package.json +1 -1
  31. package/sdk-dist/docs/runtime-reference/README.md +187 -0
  32. package/sdk-dist/docs/runtime-reference/entity-schema/README.md +120 -0
  33. package/sdk-dist/docs/runtime-reference/entity-schema/address.md +34 -0
  34. package/sdk-dist/docs/runtime-reference/entity-schema/boolean.md +37 -0
  35. package/sdk-dist/docs/runtime-reference/entity-schema/button.md +47 -0
  36. package/sdk-dist/docs/runtime-reference/entity-schema/checkbox.md +61 -0
  37. package/sdk-dist/docs/runtime-reference/entity-schema/datasets.md +35 -0
  38. package/sdk-dist/docs/runtime-reference/entity-schema/datetime.md +40 -0
  39. package/sdk-dist/docs/runtime-reference/entity-schema/department.md +33 -0
  40. package/sdk-dist/docs/runtime-reference/entity-schema/departments.md +34 -0
  41. package/sdk-dist/docs/runtime-reference/entity-schema/divider.md +39 -0
  42. package/sdk-dist/docs/runtime-reference/entity-schema/file.md +53 -0
  43. package/sdk-dist/docs/runtime-reference/entity-schema/formula.md +44 -0
  44. package/sdk-dist/docs/runtime-reference/entity-schema/image.md +52 -0
  45. package/sdk-dist/docs/runtime-reference/entity-schema/linkto.md +67 -0
  46. package/sdk-dist/docs/runtime-reference/entity-schema/location.md +32 -0
  47. package/sdk-dist/docs/runtime-reference/entity-schema/lookup.md +41 -0
  48. package/sdk-dist/docs/runtime-reference/entity-schema/member.md +37 -0
  49. package/sdk-dist/docs/runtime-reference/entity-schema/members.md +31 -0
  50. package/sdk-dist/docs/runtime-reference/entity-schema/number.md +70 -0
  51. package/sdk-dist/docs/runtime-reference/entity-schema/query.md +50 -0
  52. package/sdk-dist/docs/runtime-reference/entity-schema/radio.md +53 -0
  53. package/sdk-dist/docs/runtime-reference/entity-schema/relation.md +55 -0
  54. package/sdk-dist/docs/runtime-reference/entity-schema/relationfield.md +38 -0
  55. package/sdk-dist/docs/runtime-reference/entity-schema/rollup.md +54 -0
  56. package/sdk-dist/docs/runtime-reference/entity-schema/select.md +63 -0
  57. package/sdk-dist/docs/runtime-reference/entity-schema/selects.md +51 -0
  58. package/sdk-dist/docs/runtime-reference/entity-schema/serialnumber.md +48 -0
  59. package/sdk-dist/docs/runtime-reference/entity-schema/signature.md +31 -0
  60. package/sdk-dist/docs/runtime-reference/entity-schema/status.md +70 -0
  61. package/sdk-dist/docs/runtime-reference/entity-schema/subform.md +74 -0
  62. package/sdk-dist/docs/runtime-reference/entity-schema/tags.md +19 -0
  63. package/sdk-dist/docs/runtime-reference/entity-schema/text.md +76 -0
  64. package/sdk-dist/docs/runtime-reference/entity-schema/textarea.md +47 -0
  65. package/sdk-dist/docs/runtime-reference/entity-schema/workflow_status.md +17 -0
  66. package/sdk-dist/docs/runtime-reference/entity-schema.md +197 -0
  67. package/sdk-dist/docs/runtime-reference/examples/README.md +51 -0
  68. package/sdk-dist/docs/runtime-reference/examples/crm-01/README.md +20 -0
  69. package/sdk-dist/docs/runtime-reference/examples/mes-01/README.md +21 -0
  70. package/sdk-dist/docs/runtime-reference/examples/oms-01/README.md +183 -0
  71. package/sdk-dist/docs/runtime-reference/examples/oms-01/app-overview.md +79 -0
  72. package/sdk-dist/docs/runtime-reference/examples/oms-01/create-app.json +3 -0
  73. package/sdk-dist/docs/runtime-reference/examples/oms-01/goods-receipt.create-entity.json +3 -0
  74. package/sdk-dist/docs/runtime-reference/examples/oms-01/goods-receipt.schema.json +159 -0
  75. package/sdk-dist/docs/runtime-reference/examples/oms-01/item-master.create-entity.json +3 -0
  76. package/sdk-dist/docs/runtime-reference/examples/oms-01/item-master.schema.json +179 -0
  77. package/sdk-dist/docs/runtime-reference/examples/oms-01/picking-list.create-entity.json +3 -0
  78. package/sdk-dist/docs/runtime-reference/examples/oms-01/picking-list.schema.json +168 -0
  79. package/sdk-dist/docs/runtime-reference/examples/oms-01/purchase-order.create-entity.json +3 -0
  80. package/sdk-dist/docs/runtime-reference/examples/oms-01/purchase-order.schema.json +417 -0
  81. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.bulk-update.json +22 -0
  82. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.create-entity.json +3 -0
  83. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.query.json +10 -0
  84. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.row.insert.json +28 -0
  85. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.schema.json +398 -0
  86. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.selection.condition.json +13 -0
  87. package/sdk-dist/docs/runtime-reference/examples/oms-01/sales-order.selection.ids.json +7 -0
  88. package/sdk-dist/docs/runtime-reference/examples/oms-01/stock-issue.create-entity.json +3 -0
  89. package/sdk-dist/docs/runtime-reference/examples/oms-01/stock-issue.schema.json +137 -0
  90. package/sdk-dist/docs/runtime-reference/examples/wms-01/README.md +21 -0
  91. package/sdk-dist/docs/runtime-reference/row-crud.md +188 -0
  92. package/sdk-dist/docs/runtime-reference/search-and-bulk-actions.md +494 -0
  93. package/sdk-dist/docs/runtime-reference/table-lifecycle.md +135 -0
  94. package/sdk-dist/docs/runtime-reference/uploads.md +106 -0
  95. package/sdk-dist/docs/runtime-reference/workflow/README.md +19 -0
  96. package/src/runtime/command_registry.ts +47 -0
  97. package/src/runtime/entity_save_schema.ts +708 -0
  98. package/src/runtime/errors.ts +12 -0
  99. package/src/runtime/execute.ts +367 -12
  100. package/src/runtime/upload.ts +196 -0
  101. package/src/runtime/zod_registry.ts +156 -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 +781 -0
  105. package/src/tests/help.test.ts +60 -0
  106. package/src/tests/upload.test.ts +133 -0
@@ -18,15 +18,75 @@ test('root help prints modules', async () => {
18
18
  assert.match(out.text, /app/)
19
19
  })
20
20
 
21
+ test('root help does not require runtime env', async () => {
22
+ const out = await executeCLI('admin', ['--help'], undefined, async () => new Response('{}'))
23
+ assert.equal(out.kind, 'help')
24
+ assert.match(out.text, /modules:/)
25
+ })
26
+
21
27
  test('module help prints create-entity command', async () => {
22
28
  const out = await executeCLI('admin', ['app', '--help'], env as any, async () => new Response('{}'))
23
29
  assert.equal(out.kind, 'help')
24
30
  assert.match(out.text, /create-entity/)
25
31
  })
26
32
 
33
+ test('module help does not require runtime env', async () => {
34
+ const out = await executeCLI('user', ['workflow', '--help'], undefined, async () => new Response('{}'))
35
+ assert.equal(out.kind, 'help')
36
+ assert.match(out.text, /delete-entity-row/)
37
+ })
38
+
27
39
  test('command help prints normalized external endpoint', async () => {
28
40
  const out = await executeCLI('admin', ['app-entity-share', 'get-app-entity-shares', '--help'], env as any, async () => new Response('{}'))
29
41
  assert.equal(out.kind, 'help')
30
42
  assert.match(out.text, /endpoint: \/apps\/:app_id\/entity-shares/)
31
43
  assert.doesNotMatch(out.text, /endpoint: \/api\//)
32
44
  })
45
+
46
+ test('command help does not require runtime env', async () => {
47
+ const out = await executeCLI('user', ['workflow', 'delete-entity-row', '--help'], undefined, async () => new Response('{}'))
48
+ assert.equal(out.kind, 'help')
49
+ assert.match(out.text, /endpoint: \/entity\/:app_id\/:entity_id\/delete-item/)
50
+ })
51
+
52
+ test('command help prints runtime doc hints for request body commands', async () => {
53
+ const out = await executeCLI('user', ['workflow', 'update-entity-row', '--help'], undefined, async () => new Response('{}'))
54
+ assert.equal(out.kind, 'help')
55
+ assert.match(out.text, /docs:/)
56
+ assert.match(out.text, /\/opt\/arcubase-sdk\/docs\/runtime-reference\/row-crud\.md/)
57
+ assert.match(out.text, /\/opt\/arcubase-sdk\/docs\/runtime-reference\/examples\/README\.md/)
58
+ })
59
+
60
+ test('command help prints query-file support', async () => {
61
+ const out = await executeCLI('user', ['workflow', 'query-entity', '--help'], undefined, async () => new Response('{}'))
62
+ assert.equal(out.kind, 'help')
63
+ assert.match(out.text, /query flags: --query-file/)
64
+ })
65
+
66
+ test('command help without request body can still point to lifecycle and examples docs', async () => {
67
+ const out = await executeCLI('admin', ['entity', 'admin-get-entity-info', '--help'], undefined, async () => new Response('{}'))
68
+ assert.equal(out.kind, 'help')
69
+ assert.match(out.text, /\/opt\/arcubase-sdk\/docs\/runtime-reference\/table-lifecycle\.md/)
70
+ assert.match(out.text, /\/opt\/arcubase-sdk\/docs\/runtime-reference\/examples\/README\.md/)
71
+ })
72
+
73
+ test('admin-save-entity help prints row-operation next step', async () => {
74
+ const out = await executeCLI('admin', ['entity', 'admin-save-entity', '--help'], undefined, async () => new Response('{}'))
75
+ assert.equal(out.kind, 'help')
76
+ assert.match(out.text, /switch to arcubase for row operations/)
77
+ assert.match(out.text, /arcubase workflow insert-entity/)
78
+ assert.match(out.text, /arcubase workflow query-entity/)
79
+ })
80
+
81
+ test('wrong admin workflow command points to arcubase row command', async () => {
82
+ await assert.rejects(
83
+ () => executeCLI('admin', ['workflow', 'insert-entity'], env as any, async () => new Response('{}')),
84
+ (error: any) => {
85
+ assert.equal(error.code, 'UNKNOWN_COMMAND')
86
+ assert.equal(error.details?.reason, 'workflow insert-entity is a row operation, not an arcubase-admin command')
87
+ assert.equal(error.details?.hint, 'use: arcubase workflow insert-entity')
88
+ assert.ok((error.details?.suggestions ?? []).includes('arcubase workflow insert-entity'))
89
+ return true
90
+ }
91
+ )
92
+ })
@@ -0,0 +1,133 @@
1
+ import test from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import fs from 'fs'
4
+ import os from 'os'
5
+ import path from 'path'
6
+ import { executeCLI } from '../runtime/execute.js'
7
+
8
+ const env = {
9
+ ARCUBASE_BASE_URL: 'https://arcubase.example.com',
10
+ ARCUBASE_TENANT_ID: 'tenant_1',
11
+ ARCUBASE_ACCESS_TOKEN: 'tok',
12
+ ARCUBASE_TRACE_ID: '',
13
+ ARCUBASE_SUBJECT_TYPE: '',
14
+ ARCUBASE_SUBJECT_ID: '',
15
+ ARCUBASE_TOKEN_EXPIRES_AT: '',
16
+ }
17
+
18
+ test('upload help works without runtime env', async () => {
19
+ const out = await executeCLI('user', ['upload', '--help'], undefined, async () => new Response('{}'))
20
+ assert.equal(out.kind, 'help')
21
+ assert.match(out.text, /arcubase upload <local-file>/)
22
+ assert.match(out.text, /uploads\.md/)
23
+ })
24
+
25
+ test('upload returns file field value array for row payloads', async () => {
26
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'arcubase-upload-'))
27
+ const sourceFile = path.join(tempDir, 'contract.pdf')
28
+ fs.writeFileSync(sourceFile, 'fake pdf bytes')
29
+
30
+ const calls: Array<{ url: string; method?: string }> = []
31
+
32
+ const result = await executeCLI(
33
+ 'user',
34
+ ['upload', sourceFile],
35
+ env as any,
36
+ async (input, init) => {
37
+ const url = String(input)
38
+ calls.push({ url, method: init?.method })
39
+ if (url === 'https://arcubase.example.com/upload/token') {
40
+ return new Response(
41
+ JSON.stringify({
42
+ data: {
43
+ id: 123456,
44
+ mode: 'aliyun-oss',
45
+ token_data: {
46
+ dir: 'upload/123456/',
47
+ policy: 'policy',
48
+ accessid: 'accessid',
49
+ signature: 'signature',
50
+ host: 'https://uploads.example.com',
51
+ },
52
+ },
53
+ }),
54
+ { status: 200, headers: { 'Content-Type': 'application/json' } },
55
+ )
56
+ }
57
+ if (url === 'https://uploads.example.com') {
58
+ return new Response('', { status: 200 })
59
+ }
60
+ throw new Error(`unexpected fetch url: ${url}`)
61
+ },
62
+ )
63
+
64
+ assert.equal(result.kind, 'result')
65
+ assert.deepEqual(calls, [
66
+ { url: 'https://arcubase.example.com/upload/token', method: 'POST' },
67
+ { url: 'https://uploads.example.com', method: 'POST' },
68
+ ])
69
+ assert.deepEqual(result.data, [
70
+ {
71
+ upload_id: 123456,
72
+ file: 'contract.pdf',
73
+ file_name: 'contract.pdf',
74
+ meta: {},
75
+ },
76
+ ])
77
+ })
78
+
79
+ test('upload supports s3-post-policy tokens', async () => {
80
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'arcubase-upload-s3-'))
81
+ const sourceFile = path.join(tempDir, 'contract.pdf')
82
+ fs.writeFileSync(sourceFile, 'fake pdf bytes')
83
+
84
+ const calls: Array<{ url: string; method?: string }> = []
85
+
86
+ const result = await executeCLI(
87
+ 'user',
88
+ ['upload', sourceFile],
89
+ env as any,
90
+ async (input, init) => {
91
+ const url = String(input)
92
+ calls.push({ url, method: init?.method })
93
+ if (url === 'https://arcubase.example.com/upload/token') {
94
+ return new Response(
95
+ JSON.stringify({
96
+ data: {
97
+ id: 654321,
98
+ mode: 's3-post-policy',
99
+ token_data: {
100
+ dir: 'upload/654321/',
101
+ policy: 'policy',
102
+ host: 'https://uploads.example.com/private-bucket',
103
+ x_amz_algorithm: 'AWS4-HMAC-SHA256',
104
+ x_amz_credential: 'test/20260504/us-east-1/s3/aws4_request',
105
+ x_amz_date: '20260504T010203Z',
106
+ x_amz_signature: 'abc123',
107
+ },
108
+ },
109
+ }),
110
+ { status: 200, headers: { 'Content-Type': 'application/json' } },
111
+ )
112
+ }
113
+ if (url === 'https://uploads.example.com/private-bucket') {
114
+ return new Response('', { status: 200 })
115
+ }
116
+ throw new Error(`unexpected fetch url: ${url}`)
117
+ },
118
+ )
119
+
120
+ assert.equal(result.kind, 'result')
121
+ assert.deepEqual(calls, [
122
+ { url: 'https://arcubase.example.com/upload/token', method: 'POST' },
123
+ { url: 'https://uploads.example.com/private-bucket', method: 'POST' },
124
+ ])
125
+ assert.deepEqual(result.data, [
126
+ {
127
+ upload_id: 654321,
128
+ file: 'contract.pdf',
129
+ file_name: 'contract.pdf',
130
+ meta: {},
131
+ },
132
+ ])
133
+ })