@carthooks/arcubase-cli 0.1.7 → 0.1.9
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 +1042 -5056
- package/bundle/arcubase.mjs +1042 -5056
- package/dist/generated/command_registry.generated.d.ts +693 -2812
- package/dist/generated/command_registry.generated.d.ts.map +1 -1
- package/dist/generated/command_registry.generated.js +812 -4100
- package/dist/generated/type_index.generated.d.ts +8 -397
- package/dist/generated/type_index.generated.d.ts.map +1 -1
- package/dist/generated/type_index.generated.js +8 -403
- package/dist/generated/zod_registry.generated.d.ts +33 -261
- package/dist/generated/zod_registry.generated.d.ts.map +1 -1
- package/dist/generated/zod_registry.generated.js +36 -365
- package/dist/runtime/body_loader.d.ts.map +1 -1
- package/dist/runtime/body_loader.js +12 -0
- package/dist/runtime/command_registry.d.ts +3 -21
- package/dist/runtime/command_registry.d.ts.map +1 -1
- package/dist/runtime/command_registry.js +17 -23
- package/dist/runtime/execute.d.ts +3 -3
- package/dist/runtime/execute.d.ts.map +1 -1
- package/dist/runtime/execute.js +53 -157
- package/dist/runtime/http.js +1 -1
- package/dist/runtime/upload.js +3 -3
- package/dist/runtime/zod_registry.d.ts.map +1 -1
- package/dist/runtime/zod_registry.js +7 -24
- package/dist/tests/command_registry.test.js +81 -28
- package/dist/tests/execute_validation.test.js +175 -510
- package/dist/tests/help.test.js +39 -62
- package/dist/tests/upload.test.js +4 -4
- package/dist/tests/zod_registry.test.js +0 -10
- package/package.json +1 -1
- package/sdk-dist/docs/runtime-reference/README.md +20 -30
- package/sdk-dist/docs/runtime-reference/entity-schema/README.md +4 -5
- package/sdk-dist/docs/runtime-reference/entity-schema/linkto.md +3 -3
- package/sdk-dist/docs/runtime-reference/entity-schema/query.md +3 -3
- package/sdk-dist/docs/runtime-reference/entity-schema/relation.md +3 -3
- package/sdk-dist/docs/runtime-reference/entity-schema/relationfield.md +3 -3
- package/sdk-dist/docs/runtime-reference/entity-schema/subform.md +2 -2
- package/sdk-dist/docs/runtime-reference/entity-schema.md +4 -4
- package/sdk-dist/docs/runtime-reference/examples/README.md +2 -2
- package/sdk-dist/docs/runtime-reference/examples/oms-01/README.md +12 -12
- package/sdk-dist/docs/runtime-reference/examples/oms-01/app-overview.md +1 -1
- package/sdk-dist/docs/runtime-reference/row-crud.md +11 -32
- package/sdk-dist/docs/runtime-reference/search-and-bulk-actions.md +16 -47
- package/sdk-dist/docs/runtime-reference/table-lifecycle.md +11 -27
- package/sdk-dist/docs/runtime-reference/uploads.md +1 -1
- package/sdk-dist/docs/runtime-reference/workflow/README.md +19 -0
- package/sdk-dist/generated/command_registry.generated.ts +814 -4102
- package/sdk-dist/generated/type_index.generated.ts +8 -403
- package/sdk-dist/generated/zod_registry.generated.ts +44 -500
- package/sdk-dist/types/app.ts +3 -10
- package/sdk-dist/types/common.ts +7 -0
- package/sdk-dist/types/global-action.ts +2 -1
- package/src/generated/command_registry.generated.ts +814 -4102
- package/src/generated/type_index.generated.ts +8 -403
- package/src/generated/zod_registry.generated.ts +44 -500
- package/src/runtime/body_loader.ts +11 -0
- package/src/runtime/command_registry.ts +22 -44
- package/src/runtime/execute.ts +157 -165
- package/src/runtime/http.ts +1 -1
- package/src/runtime/upload.ts +3 -3
- package/src/runtime/zod_registry.ts +7 -25
- package/src/tests/command_registry.test.ts +81 -31
- package/src/tests/execute_validation.test.ts +236 -603
- package/src/tests/help.test.ts +47 -66
- package/src/tests/upload.test.ts +4 -4
- package/src/tests/zod_registry.test.ts +0 -13
- package/sdk-dist/docs/runtime-reference/app-discovery.md +0 -68
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
import { adminCommands, userCommands } from '../generated/command_registry.generated.js';
|
|
2
2
|
export { adminCommands, userCommands };
|
|
3
3
|
export type CommandScope = 'admin' | 'user';
|
|
4
|
-
type
|
|
5
|
-
type CustomCommandDef = {
|
|
6
|
-
scope: CommandScope;
|
|
7
|
-
module: string;
|
|
8
|
-
functionName: string;
|
|
9
|
-
commandPath: readonly [string, string];
|
|
10
|
-
method: string;
|
|
11
|
-
endpoint: string;
|
|
12
|
-
endpointParams: readonly string[];
|
|
13
|
-
controller: string;
|
|
14
|
-
requestType: string | null;
|
|
15
|
-
scalarParams: readonly {
|
|
16
|
-
name: string;
|
|
17
|
-
type: string;
|
|
18
|
-
hasDefault: boolean;
|
|
19
|
-
}[];
|
|
20
|
-
responseType: string;
|
|
21
|
-
};
|
|
22
|
-
export type CommandDef = GeneratedCommandDef | CustomCommandDef;
|
|
4
|
+
export type CommandDef = (typeof adminCommands)[number] | (typeof userCommands)[number];
|
|
23
5
|
export declare function listCommands(scope: CommandScope): readonly CommandDef[];
|
|
24
|
-
export declare function findCommand(scope: CommandScope, moduleName: string, commandName
|
|
6
|
+
export declare function findCommand(scope: CommandScope, moduleName: string, commandName?: string | null): CommandDef | null;
|
|
25
7
|
export declare function listModules(scope: CommandScope): string[];
|
|
26
8
|
export declare function listModuleCommands(scope: CommandScope, moduleName: string): readonly CommandDef[];
|
|
27
9
|
export type CommandSuggestion = {
|
|
28
10
|
scope: CommandScope;
|
|
29
11
|
moduleName: string;
|
|
30
|
-
commandName: string;
|
|
12
|
+
commandName: string | null;
|
|
31
13
|
binary: 'arcubase-admin' | 'arcubase';
|
|
32
14
|
score: number;
|
|
33
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/command_registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAExF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA;AAEtC,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAA;AAC3C,
|
|
1
|
+
{"version":3,"file":"command_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/command_registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAExF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA;AAEtC,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAA;AAC3C,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvF,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,UAAU,EAAE,CAEvE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,CAUnH;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAEjG;AAmBD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,YAAY,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAAA;IACrC,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,iBAAiB,EAAE,CA0B9G"}
|
|
@@ -1,28 +1,18 @@
|
|
|
1
1
|
import { adminCommands, userCommands } from '../generated/command_registry.generated.js';
|
|
2
2
|
export { adminCommands, userCommands };
|
|
3
|
-
const customAdminCommands = [
|
|
4
|
-
{
|
|
5
|
-
scope: 'admin',
|
|
6
|
-
module: 'app',
|
|
7
|
-
functionName: 'inventory',
|
|
8
|
-
commandPath: ['app', 'inventory'],
|
|
9
|
-
method: 'GET',
|
|
10
|
-
endpoint: '/apps',
|
|
11
|
-
endpointParams: [],
|
|
12
|
-
controller: 'Runtime.AppInventory',
|
|
13
|
-
requestType: null,
|
|
14
|
-
scalarParams: [],
|
|
15
|
-
responseType: 'AppInventoryRespVO',
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
const customUserCommands = [];
|
|
19
3
|
export function listCommands(scope) {
|
|
20
|
-
return scope === 'admin'
|
|
21
|
-
? [...adminCommands, ...customAdminCommands]
|
|
22
|
-
: [...userCommands, ...customUserCommands];
|
|
4
|
+
return scope === 'admin' ? adminCommands : userCommands;
|
|
23
5
|
}
|
|
24
6
|
export function findCommand(scope, moduleName, commandName) {
|
|
25
|
-
return listCommands(scope).find((item) =>
|
|
7
|
+
return listCommands(scope).find((item) => {
|
|
8
|
+
if (item.commandPath[0] !== moduleName) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (item.commandPath.length === 1) {
|
|
12
|
+
return !commandName;
|
|
13
|
+
}
|
|
14
|
+
return item.commandPath[1] === commandName;
|
|
15
|
+
}) ?? null;
|
|
26
16
|
}
|
|
27
17
|
export function listModules(scope) {
|
|
28
18
|
return [...new Set(listCommands(scope).map((item) => item.commandPath[0]))].sort();
|
|
@@ -48,9 +38,10 @@ export function findCommandSuggestions(moduleName, commandName, limit = 3) {
|
|
|
48
38
|
const suggestions = [];
|
|
49
39
|
for (const scope of ['admin', 'user']) {
|
|
50
40
|
for (const command of listCommands(scope)) {
|
|
51
|
-
const
|
|
41
|
+
const candidateModule = command.commandPath[0];
|
|
42
|
+
const candidateCommand = command.commandPath.length > 1 ? command.commandPath[1] ?? null : null;
|
|
52
43
|
const moduleScore = candidateModule === moduleName ? 0 : levenshtein(candidateModule, moduleName || '');
|
|
53
|
-
const commandScore = candidateCommand === commandName ? 0 : levenshtein(candidateCommand, commandName || '');
|
|
44
|
+
const commandScore = candidateCommand === commandName ? 0 : levenshtein(candidateCommand ?? '', commandName || '');
|
|
54
45
|
const score = commandScore * 3 + moduleScore;
|
|
55
46
|
suggestions.push({
|
|
56
47
|
scope,
|
|
@@ -62,6 +53,9 @@ export function findCommandSuggestions(moduleName, commandName, limit = 3) {
|
|
|
62
53
|
}
|
|
63
54
|
}
|
|
64
55
|
return suggestions
|
|
65
|
-
.sort((a, b) => a.score - b.score ||
|
|
56
|
+
.sort((a, b) => a.score - b.score ||
|
|
57
|
+
a.binary.localeCompare(b.binary) ||
|
|
58
|
+
a.moduleName.localeCompare(b.moduleName) ||
|
|
59
|
+
(a.commandName ?? '').localeCompare(b.commandName ?? ''))
|
|
66
60
|
.slice(0, limit);
|
|
67
61
|
}
|
|
@@ -2,16 +2,16 @@ import { type RuntimeEnv } from './env.js';
|
|
|
2
2
|
import { type CommandScope } from './command_registry.js';
|
|
3
3
|
export type CommandExecutionSummary = {
|
|
4
4
|
scope: CommandScope;
|
|
5
|
-
commandPath: readonly [
|
|
5
|
+
commandPath: readonly string[];
|
|
6
6
|
method: string;
|
|
7
7
|
endpoint: string;
|
|
8
8
|
requestType: string | null;
|
|
9
9
|
pathFlags: readonly string[];
|
|
10
|
-
|
|
10
|
+
queryFlags: readonly string[];
|
|
11
11
|
};
|
|
12
12
|
export declare function renderRootHelp(scope: CommandScope): string;
|
|
13
13
|
export declare function renderModuleHelp(scope: CommandScope, moduleName: string): string;
|
|
14
|
-
export declare function renderCommandHelp(scope: CommandScope, moduleName: string, commandName
|
|
14
|
+
export declare function renderCommandHelp(scope: CommandScope, moduleName: string, commandName?: string): string;
|
|
15
15
|
export declare function summarizeCommand(scope: CommandScope, moduleName: string, commandName: string): CommandExecutionSummary;
|
|
16
16
|
export declare function executeCLI(scope: CommandScope, argv: string[], env?: RuntimeEnv, fetchImpl?: typeof fetch): Promise<any>;
|
|
17
17
|
//# sourceMappingURL=execute.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAwE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAK/H,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAwE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAK/H,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;AAYD,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAa1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAkBhF;AAOD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CA8BvG;AAoSD,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,CAiKrI"}
|
package/dist/runtime/execute.js
CHANGED
|
@@ -9,115 +9,15 @@ import { renderUploadHelp, uploadLocalFile } from './upload.js';
|
|
|
9
9
|
function summarizeUploadResult(value) {
|
|
10
10
|
return value;
|
|
11
11
|
}
|
|
12
|
-
function parseJSONResponse(raw) {
|
|
13
|
-
if (!raw)
|
|
14
|
-
return null;
|
|
15
|
-
try {
|
|
16
|
-
return JSON.parse(raw);
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return raw;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function unwrapResponseData(payload) {
|
|
23
|
-
return isRecord(payload) && 'data' in payload ? payload.data : payload;
|
|
24
|
-
}
|
|
25
|
-
function formatUpstreamError(payload) {
|
|
26
|
-
if (typeof payload === 'string') {
|
|
27
|
-
return payload;
|
|
28
|
-
}
|
|
29
|
-
if (isRecord(payload) && isRecord(payload.error) && typeof payload.error.message === 'string') {
|
|
30
|
-
return payload.error.message;
|
|
31
|
-
}
|
|
32
|
-
return JSON.stringify(payload);
|
|
33
|
-
}
|
|
34
|
-
function extractApps(payload) {
|
|
35
|
-
const data = unwrapResponseData(payload);
|
|
36
|
-
if (!Array.isArray(data))
|
|
37
|
-
return [];
|
|
38
|
-
return data
|
|
39
|
-
.filter((item) => isRecord(item))
|
|
40
|
-
.filter((item) => item.id !== undefined && typeof item.name === 'string')
|
|
41
|
-
.map((item) => ({
|
|
42
|
-
id: String(item.id),
|
|
43
|
-
name: item.name,
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
function extractEntities(payload) {
|
|
47
|
-
const data = unwrapResponseData(payload);
|
|
48
|
-
if (!Array.isArray(data))
|
|
49
|
-
return [];
|
|
50
|
-
return data
|
|
51
|
-
.filter((item) => isRecord(item))
|
|
52
|
-
.filter((item) => item.id !== undefined && typeof item.name === 'string')
|
|
53
|
-
.map((item) => ({
|
|
54
|
-
id: String(item.id),
|
|
55
|
-
name: item.name,
|
|
56
|
-
}));
|
|
57
|
-
}
|
|
58
|
-
async function executeAppInventory(runtimeEnv, fetchImpl) {
|
|
59
|
-
const appsResponse = await fetchImpl(buildURL(runtimeEnv.ARCUBASE_BASE_URL, '/apps'), {
|
|
60
|
-
method: 'GET',
|
|
61
|
-
headers: buildRequestHeaders(runtimeEnv),
|
|
62
|
-
});
|
|
63
|
-
const appsRaw = await appsResponse.text();
|
|
64
|
-
const appsPayload = parseJSONResponse(appsRaw);
|
|
65
|
-
if (!appsResponse.ok) {
|
|
66
|
-
throw new CLIError('UPSTREAM_REQUEST_FAILED', formatUpstreamError(appsPayload), 1);
|
|
67
|
-
}
|
|
68
|
-
if (isRecord(appsPayload) && appsPayload.error) {
|
|
69
|
-
throw new CLIError('UPSTREAM_BODY_ERROR', formatUpstreamError(appsPayload), 1, {
|
|
70
|
-
endpoint: '/apps',
|
|
71
|
-
method: 'GET',
|
|
72
|
-
upstreamError: appsPayload.error,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
const apps = extractApps(appsPayload);
|
|
76
|
-
const items = [];
|
|
77
|
-
for (const app of apps) {
|
|
78
|
-
const entitiesResponse = await fetchImpl(buildURL(runtimeEnv.ARCUBASE_BASE_URL, `/apps/${encodeURIComponent(app.id)}/entities`), {
|
|
79
|
-
method: 'POST',
|
|
80
|
-
headers: {
|
|
81
|
-
...buildRequestHeaders(runtimeEnv),
|
|
82
|
-
'Content-Type': 'application/json',
|
|
83
|
-
},
|
|
84
|
-
body: JSON.stringify({}),
|
|
85
|
-
});
|
|
86
|
-
const entitiesRaw = await entitiesResponse.text();
|
|
87
|
-
const entitiesPayload = parseJSONResponse(entitiesRaw);
|
|
88
|
-
if (!entitiesResponse.ok) {
|
|
89
|
-
throw new CLIError('UPSTREAM_REQUEST_FAILED', formatUpstreamError(entitiesPayload), 1);
|
|
90
|
-
}
|
|
91
|
-
if (isRecord(entitiesPayload) && entitiesPayload.error) {
|
|
92
|
-
throw new CLIError('UPSTREAM_BODY_ERROR', formatUpstreamError(entitiesPayload), 1, {
|
|
93
|
-
endpoint: `/apps/${app.id}/entities`,
|
|
94
|
-
method: 'POST',
|
|
95
|
-
upstreamError: entitiesPayload.error,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
items.push({
|
|
99
|
-
...app,
|
|
100
|
-
entities: extractEntities(entitiesPayload),
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
kind: 'result',
|
|
105
|
-
commandPath: ['app', 'inventory'],
|
|
106
|
-
status: 200,
|
|
107
|
-
data: {
|
|
108
|
-
apps: items,
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
12
|
export function renderRootHelp(scope) {
|
|
113
13
|
const binary = scope === 'admin' ? 'arcubase-admin' : 'arcubase';
|
|
114
14
|
const items = listModules(scope).map((item) => ` - ${item}`);
|
|
115
15
|
return [
|
|
116
|
-
`${binary} <
|
|
16
|
+
`${binary} <command> [subcommand] [flags]`,
|
|
117
17
|
'',
|
|
118
18
|
...(scope === 'admin'
|
|
119
|
-
? ['use arcubase-admin for app,
|
|
120
|
-
: ['use arcubase for
|
|
19
|
+
? ['use arcubase-admin for app, table, access-rule, and workflow management', '']
|
|
20
|
+
: ['use arcubase for entry, table, row, upload, profile, and workflow actions', '']),
|
|
121
21
|
'modules:',
|
|
122
22
|
...items,
|
|
123
23
|
...(scope === 'user' ? ['', 'special commands:', ' - upload <local-file>'] : []),
|
|
@@ -126,60 +26,50 @@ export function renderRootHelp(scope) {
|
|
|
126
26
|
export function renderModuleHelp(scope, moduleName) {
|
|
127
27
|
const items = listModuleCommands(scope, moduleName);
|
|
128
28
|
if (items.length === 0) {
|
|
129
|
-
const suggestions = findCommandSuggestions(moduleName, '').map((item) => `${item.binary} ${item.moduleName} ${item.commandName}`);
|
|
29
|
+
const suggestions = findCommandSuggestions(moduleName, '').map((item) => `${item.binary} ${item.moduleName}${item.commandName ? ` ${item.commandName}` : ''}`);
|
|
130
30
|
throw new CLIError('UNKNOWN_MODULE', `unknown module: ${moduleName}`, 2, suggestions.length > 0 ? { suggestions } : undefined);
|
|
131
31
|
}
|
|
32
|
+
if (items.length === 1 && items[0].commandPath.length === 1) {
|
|
33
|
+
return renderCommandHelp(scope, moduleName);
|
|
34
|
+
}
|
|
132
35
|
return [
|
|
133
36
|
`${scope === 'admin' ? 'arcubase-admin' : 'arcubase'} ${moduleName} <command> [flags]`,
|
|
134
37
|
'',
|
|
135
38
|
...(scope === 'admin'
|
|
136
|
-
? ['use arcubase-admin for app,
|
|
137
|
-
: ['use arcubase for
|
|
39
|
+
? ['use arcubase-admin for app, table, access-rule, and workflow management', '']
|
|
40
|
+
: ['use arcubase for entry, table, row, upload, profile, and workflow actions', '']),
|
|
138
41
|
'commands:',
|
|
139
|
-
...items.map((item) => ` - ${item.commandPath[1]}`),
|
|
42
|
+
...items.filter((item) => item.commandPath.length > 1).map((item) => ` - ${item.commandPath[1]}`),
|
|
140
43
|
].join('\n');
|
|
141
44
|
}
|
|
142
45
|
function buildUnknownCommandDetails(scope, moduleName, commandName) {
|
|
143
|
-
const suggestions = findCommandSuggestions(moduleName, commandName).map((item) => `${item.binary} ${item.moduleName} ${item.commandName}`);
|
|
144
|
-
if (scope === 'admin' && moduleName === 'workflow' && suggestions.some((item) => item.startsWith('arcubase rows '))) {
|
|
145
|
-
return {
|
|
146
|
-
suggestions,
|
|
147
|
-
reason: `${moduleName} ${commandName} is not a valid command group; use arcubase rows for row operations`,
|
|
148
|
-
hint: `use: arcubase rows ${commandName}`,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
46
|
+
const suggestions = findCommandSuggestions(moduleName, commandName).map((item) => `${item.binary} ${item.moduleName}${item.commandName ? ` ${item.commandName}` : ''}`);
|
|
151
47
|
return suggestions.length > 0 ? { suggestions } : undefined;
|
|
152
48
|
}
|
|
153
49
|
export function renderCommandHelp(scope, moduleName, commandName) {
|
|
154
50
|
const command = findCommand(scope, moduleName, commandName);
|
|
155
51
|
if (!command) {
|
|
156
|
-
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName} ${commandName}`, 2, buildUnknownCommandDetails(scope, moduleName, commandName));
|
|
52
|
+
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName}${commandName ? ` ${commandName}` : ''}`, 2, buildUnknownCommandDetails(scope, moduleName, commandName ?? ''));
|
|
157
53
|
}
|
|
158
54
|
const docHints = [
|
|
159
55
|
...getCommandDocHints(`${scope}.${command.module}.${command.functionName}`),
|
|
160
56
|
...(command.requestType ? getDocHints(command.requestType) : []),
|
|
161
57
|
].filter((item, index, list) => list.findIndex((candidate) => candidate.file === item.file) === index);
|
|
58
|
+
const pathFlags = command.pathParams.filter((item) => !getFixedValue(item)).map((item) => `--${item.flag}`);
|
|
59
|
+
const queryFlags = command.queryParams.filter((item) => !getFixedValue(item)).map((item) => `--${item.flag}`);
|
|
162
60
|
return [
|
|
163
|
-
`${scope === 'admin' ? 'arcubase-admin' : 'arcubase'} ${
|
|
61
|
+
`${scope === 'admin' ? 'arcubase-admin' : 'arcubase'} ${command.commandPath.join(' ')}`,
|
|
164
62
|
`method: ${command.method}`,
|
|
165
63
|
`endpoint: ${normalizeExternalEndpoint(command.endpoint)}`,
|
|
166
|
-
command.requestType ? `body: ${command.requestType} via --body-file` : 'body: none',
|
|
167
|
-
'query flags: --query-file',
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...(scope === 'admin' && moduleName === 'entity' && commandName === 'admin-save-entity'
|
|
64
|
+
command.requestType ? `body: ${command.requestType} via --body-file or --body-json` : 'body: none',
|
|
65
|
+
queryFlags.length ? `query flags: ${queryFlags.join(', ')}, --query-file` : 'query flags: --query-file',
|
|
66
|
+
pathFlags.length ? `path flags: ${pathFlags.join(', ')}` : 'path flags: none',
|
|
67
|
+
...(scope === 'admin' && command.commandPath[0] === 'table' && command.commandPath[1] === 'update-schema'
|
|
171
68
|
? [
|
|
172
69
|
'next step:',
|
|
173
70
|
' - switch to arcubase for row operations',
|
|
174
|
-
' - row
|
|
175
|
-
' - row query: arcubase
|
|
176
|
-
]
|
|
177
|
-
: []),
|
|
178
|
-
...(scope === 'admin' && moduleName === 'app' && commandName === 'inventory'
|
|
179
|
-
? [
|
|
180
|
-
'purpose:',
|
|
181
|
-
' - list all accessible apps and each app entity list in one call sequence',
|
|
182
|
-
' - use this before asking the user for app_id',
|
|
71
|
+
' - row create: arcubase row create --app-id <app_id> --table-id <table_id> --body-file insert.json',
|
|
72
|
+
' - row query: arcubase row query --app-id <app_id> --table-id <table_id> --body-file query.json',
|
|
183
73
|
]
|
|
184
74
|
: []),
|
|
185
75
|
...(docHints.length > 0
|
|
@@ -205,15 +95,21 @@ function coerceScalar(value, typeText) {
|
|
|
205
95
|
}
|
|
206
96
|
return value;
|
|
207
97
|
}
|
|
208
|
-
function
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
98
|
+
function getFixedValue(value) {
|
|
99
|
+
if (!('fixedValue' in value)) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
const fixedValue = value.fixedValue;
|
|
103
|
+
return typeof fixedValue === 'string' ? fixedValue : undefined;
|
|
104
|
+
}
|
|
105
|
+
function resolveEndpoint(command, flags) {
|
|
106
|
+
let resolved = command.endpoint;
|
|
107
|
+
for (const mapping of command.pathParams) {
|
|
108
|
+
const value = getFixedValue(mapping) ?? flagValue(flags, mapping.flag);
|
|
213
109
|
if (!value) {
|
|
214
|
-
throw new CLIError('MISSING_PATH_FLAG', `missing required flag --${
|
|
110
|
+
throw new CLIError('MISSING_PATH_FLAG', `missing required flag --${mapping.flag}`, 2);
|
|
215
111
|
}
|
|
216
|
-
resolved = resolved.replace(`:${
|
|
112
|
+
resolved = resolved.replace(`:${mapping.param}`, encodeURIComponent(value));
|
|
217
113
|
}
|
|
218
114
|
return resolved;
|
|
219
115
|
}
|
|
@@ -222,12 +118,11 @@ function buildScalarQuery(command, flags) {
|
|
|
222
118
|
return undefined;
|
|
223
119
|
}
|
|
224
120
|
const out = {};
|
|
225
|
-
for (const scalar of command.
|
|
226
|
-
const
|
|
227
|
-
const value = flagValue(flags, flagName);
|
|
121
|
+
for (const scalar of command.queryParams) {
|
|
122
|
+
const value = getFixedValue(scalar) ?? flagValue(flags, scalar.flag);
|
|
228
123
|
if (value === undefined)
|
|
229
124
|
continue;
|
|
230
|
-
out[scalar.
|
|
125
|
+
out[scalar.key] = coerceScalar(value, scalar.type);
|
|
231
126
|
}
|
|
232
127
|
return Object.keys(out).length > 0 ? out : undefined;
|
|
233
128
|
}
|
|
@@ -249,7 +144,7 @@ function extractEntityFields(payload) {
|
|
|
249
144
|
}));
|
|
250
145
|
}
|
|
251
146
|
async function fetchEntityFields(runtimeEnv, appId, entityId, fetchImpl) {
|
|
252
|
-
const response = await fetchImpl(buildURL(runtimeEnv.ARCUBASE_BASE_URL, `/entity/${encodeURIComponent(appId)}/${encodeURIComponent(entityId)}`), {
|
|
147
|
+
const response = await fetchImpl(buildURL(runtimeEnv.ARCUBASE_BASE_URL, `/api/entity/${encodeURIComponent(appId)}/${encodeURIComponent(entityId)}`), {
|
|
253
148
|
method: 'GET',
|
|
254
149
|
headers: buildRequestHeaders(runtimeEnv),
|
|
255
150
|
});
|
|
@@ -272,7 +167,7 @@ async function fetchEntityFields(runtimeEnv, appId, entityId, fetchImpl) {
|
|
|
272
167
|
? upstreamError
|
|
273
168
|
: JSON.stringify(upstreamError);
|
|
274
169
|
throw new CLIError('UPSTREAM_BODY_ERROR', upstreamMessage, 1, {
|
|
275
|
-
endpoint: `/entity/${appId}/${entityId}`,
|
|
170
|
+
endpoint: `/api/entity/${appId}/${entityId}`,
|
|
276
171
|
method: 'GET',
|
|
277
172
|
upstreamError,
|
|
278
173
|
});
|
|
@@ -304,7 +199,7 @@ async function validateFileFieldPayloads(scope, command, runtimeEnv, flags, body
|
|
|
304
199
|
return;
|
|
305
200
|
}
|
|
306
201
|
const appId = flagValue(flags, 'app-id');
|
|
307
|
-
const entityId = flagValue(flags, '
|
|
202
|
+
const entityId = flagValue(flags, 'table-id');
|
|
308
203
|
if (!appId || !entityId) {
|
|
309
204
|
return;
|
|
310
205
|
}
|
|
@@ -392,7 +287,7 @@ function validateActionSpecificBody(scope, command, flags, body) {
|
|
|
392
287
|
if (!isRecord(body) || !command.requestType) {
|
|
393
288
|
return;
|
|
394
289
|
}
|
|
395
|
-
if (command.
|
|
290
|
+
if (command.commandPath[0] === 'row' && command.commandPath[1] === 'selection-action') {
|
|
396
291
|
const action = flagValue(flags, 'action');
|
|
397
292
|
const selection = body.selection;
|
|
398
293
|
if (!isRecord(selection) || typeof selection.type !== 'string') {
|
|
@@ -403,7 +298,7 @@ function validateActionSpecificBody(scope, command, flags, body) {
|
|
|
403
298
|
const conditionKeys = condition ? Object.keys(condition).filter((key) => key !== 'selectAll') : [];
|
|
404
299
|
if (action === 'query') {
|
|
405
300
|
if (type === 'condition') {
|
|
406
|
-
throwBodyValidationFailure('selection.type=condition is not supported for action=query; use selection.type=ids or selection.type=all, or use
|
|
301
|
+
throwBodyValidationFailure('selection.type=condition is not supported for action=query; use selection.type=ids or selection.type=all, or use row query for search conditions', command.requestType, 'body.selection.type', scope, command);
|
|
407
302
|
}
|
|
408
303
|
return;
|
|
409
304
|
}
|
|
@@ -424,10 +319,10 @@ export function summarizeCommand(scope, moduleName, commandName) {
|
|
|
424
319
|
scope,
|
|
425
320
|
commandPath: command.commandPath,
|
|
426
321
|
method: command.method,
|
|
427
|
-
endpoint:
|
|
322
|
+
endpoint: command.endpoint,
|
|
428
323
|
requestType: command.requestType,
|
|
429
|
-
pathFlags: command.
|
|
430
|
-
|
|
324
|
+
pathFlags: command.pathParams.filter((item) => !getFixedValue(item)).map((item) => item.flag),
|
|
325
|
+
queryFlags: command.queryParams.filter((item) => !getFixedValue(item)).map((item) => item.flag),
|
|
431
326
|
};
|
|
432
327
|
}
|
|
433
328
|
export async function executeCLI(scope, argv, env, fetchImpl = fetch) {
|
|
@@ -459,7 +354,8 @@ export async function executeCLI(scope, argv, env, fetchImpl = fetch) {
|
|
|
459
354
|
if (!moduleName) {
|
|
460
355
|
return { kind: 'help', text: renderRootHelp(scope) };
|
|
461
356
|
}
|
|
462
|
-
|
|
357
|
+
const singleTokenCommand = !commandName ? findCommand(scope, moduleName) : null;
|
|
358
|
+
if (!commandName && !singleTokenCommand) {
|
|
463
359
|
return { kind: 'help', text: renderModuleHelp(scope, moduleName) };
|
|
464
360
|
}
|
|
465
361
|
if (hasFlag(parsed.flags, 'help')) {
|
|
@@ -468,20 +364,20 @@ export async function executeCLI(scope, argv, env, fetchImpl = fetch) {
|
|
|
468
364
|
const runtimeEnv = env ?? loadRuntimeEnv(scope);
|
|
469
365
|
const command = findCommand(scope, moduleName, commandName);
|
|
470
366
|
if (!command) {
|
|
471
|
-
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName} ${commandName}`, 2, buildUnknownCommandDetails(scope, moduleName, commandName));
|
|
472
|
-
}
|
|
473
|
-
if (scope === 'admin' && moduleName === 'app' && commandName === 'inventory') {
|
|
474
|
-
return executeAppInventory(runtimeEnv, fetchImpl);
|
|
367
|
+
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName}${commandName ? ` ${commandName}` : ''}`, 2, buildUnknownCommandDetails(scope, moduleName, commandName ?? ''));
|
|
475
368
|
}
|
|
476
|
-
const endpoint =
|
|
369
|
+
const endpoint = resolveEndpoint(command, parsed.flags);
|
|
477
370
|
const scalarQuery = buildScalarQuery(command, parsed.flags);
|
|
478
371
|
const fileQuery = loadQueryFromFlags(parsed.flags);
|
|
479
372
|
const query = { ...(scalarQuery ?? {}), ...(fileQuery ?? {}) };
|
|
480
373
|
const body = loadBodyFromFlags(parsed.flags);
|
|
481
374
|
let validatedBody = body;
|
|
375
|
+
if (!command.requestType && body !== undefined) {
|
|
376
|
+
throw new CLIError('BODY_JSON_NOT_SUPPORTED', `command does not accept a request body: ${moduleName} ${commandName}`, 2);
|
|
377
|
+
}
|
|
482
378
|
if (command.requestType) {
|
|
483
379
|
if (body === undefined) {
|
|
484
|
-
throw new CLIError('MISSING_BODY_FILE', `command requires --body-file for ${command.requestType}`, 2);
|
|
380
|
+
throw new CLIError('MISSING_BODY_FILE', `command requires --body-file or --body-json for ${command.requestType}`, 2);
|
|
485
381
|
}
|
|
486
382
|
const schema = getBodySchema(command.requestType);
|
|
487
383
|
if (schema) {
|
package/dist/runtime/http.js
CHANGED
|
@@ -18,7 +18,7 @@ export function normalizeExternalEndpoint(endpoint) {
|
|
|
18
18
|
return trimmed;
|
|
19
19
|
}
|
|
20
20
|
export function buildURL(baseURL, endpoint, query) {
|
|
21
|
-
const url = new URL(
|
|
21
|
+
const url = new URL(endpoint, baseURL.endsWith('/') ? baseURL : `${baseURL}/`);
|
|
22
22
|
if (query) {
|
|
23
23
|
for (const [key, value] of Object.entries(query)) {
|
|
24
24
|
if (value === undefined || value === null)
|
package/dist/runtime/upload.js
CHANGED
|
@@ -33,7 +33,7 @@ function requireTokenPayload(payload) {
|
|
|
33
33
|
? upstreamError
|
|
34
34
|
: JSON.stringify(upstreamError);
|
|
35
35
|
throw new CLIError('UPSTREAM_BODY_ERROR', message, 1, {
|
|
36
|
-
endpoint: '/upload/token',
|
|
36
|
+
endpoint: '/api/upload/token',
|
|
37
37
|
method: 'POST',
|
|
38
38
|
traceId: typeof payload.trace_id === 'string' ? payload.trace_id : undefined,
|
|
39
39
|
upstreamError,
|
|
@@ -74,7 +74,7 @@ export function renderUploadHelp() {
|
|
|
74
74
|
export async function uploadLocalFile(env, sourcePath, options, fetchImpl = fetch) {
|
|
75
75
|
const { absolutePath, bytes } = readUploadSource(sourcePath);
|
|
76
76
|
const filename = (options.filename && options.filename.trim()) || path.basename(absolutePath);
|
|
77
|
-
const tokenResponse = await fetchImpl(buildURL(env.ARCUBASE_BASE_URL, '/upload/token'), {
|
|
77
|
+
const tokenResponse = await fetchImpl(buildURL(env.ARCUBASE_BASE_URL, '/api/upload/token'), {
|
|
78
78
|
method: 'POST',
|
|
79
79
|
headers: {
|
|
80
80
|
...buildRequestHeaders(env),
|
|
@@ -88,7 +88,7 @@ export async function uploadLocalFile(env, sourcePath, options, fetchImpl = fetc
|
|
|
88
88
|
const tokenParsed = parseJSONResponse(tokenRaw);
|
|
89
89
|
if (!tokenResponse.ok) {
|
|
90
90
|
throw new CLIError('UPLOAD_TOKEN_REQUEST_FAILED', typeof tokenParsed === 'string' ? tokenParsed : JSON.stringify(tokenParsed), 1, {
|
|
91
|
-
endpoint: '/upload/token',
|
|
91
|
+
endpoint: '/api/upload/token',
|
|
92
92
|
method: 'POST',
|
|
93
93
|
});
|
|
94
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/zod_registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AA6BrC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAOjE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAQ9D;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;
|
|
1
|
+
{"version":3,"file":"zod_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/zod_registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AA6BrC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAOjE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAQ9D;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAyDD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAqBhE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAI9D;AA0DD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE,CAItE"}
|
|
@@ -42,18 +42,12 @@ const examplesIndexDocHint = {
|
|
|
42
42
|
title: 'Examples index',
|
|
43
43
|
file: '/opt/arcubase-sdk/docs/runtime-reference/examples/README.md',
|
|
44
44
|
};
|
|
45
|
-
const appDiscoveryDocHint = {
|
|
46
|
-
title: 'App discovery',
|
|
47
|
-
file: '/opt/arcubase-sdk/docs/runtime-reference/app-discovery.md',
|
|
48
|
-
};
|
|
49
45
|
const docHintIndex = {
|
|
50
46
|
AppCreateByTenantsReqVO: [
|
|
51
|
-
appDiscoveryDocHint,
|
|
52
47
|
{ title: 'Table lifecycle', file: '/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md' },
|
|
53
48
|
examplesIndexDocHint,
|
|
54
49
|
],
|
|
55
50
|
AppCreateEntityReqVO: [
|
|
56
|
-
appDiscoveryDocHint,
|
|
57
51
|
{ title: 'Table lifecycle', file: '/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md' },
|
|
58
52
|
examplesIndexDocHint,
|
|
59
53
|
],
|
|
@@ -131,25 +125,14 @@ export function getDocHints(typeName) {
|
|
|
131
125
|
}
|
|
132
126
|
const commandDocHintIndex = {
|
|
133
127
|
'admin.app.createAppByTenants': [
|
|
134
|
-
appDiscoveryDocHint,
|
|
135
128
|
{ title: 'Table lifecycle', file: '/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md' },
|
|
136
129
|
examplesIndexDocHint,
|
|
137
130
|
],
|
|
138
|
-
'admin.app.listApps': [
|
|
139
|
-
appDiscoveryDocHint,
|
|
140
|
-
examplesIndexDocHint,
|
|
141
|
-
],
|
|
142
|
-
'admin.app.inventory': [
|
|
143
|
-
appDiscoveryDocHint,
|
|
144
|
-
examplesIndexDocHint,
|
|
145
|
-
],
|
|
146
131
|
'admin.app.createEntity': [
|
|
147
|
-
appDiscoveryDocHint,
|
|
148
132
|
{ title: 'Table lifecycle', file: '/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md' },
|
|
149
133
|
examplesIndexDocHint,
|
|
150
134
|
],
|
|
151
135
|
'admin.entity.adminGetEntityInfo': [
|
|
152
|
-
appDiscoveryDocHint,
|
|
153
136
|
{ title: 'Table lifecycle', file: '/opt/arcubase-sdk/docs/runtime-reference/table-lifecycle.md' },
|
|
154
137
|
examplesIndexDocHint,
|
|
155
138
|
],
|
|
@@ -159,34 +142,34 @@ const commandDocHintIndex = {
|
|
|
159
142
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
160
143
|
examplesIndexDocHint,
|
|
161
144
|
],
|
|
162
|
-
'user.
|
|
145
|
+
'user.workflow.insertEntity': [
|
|
163
146
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
164
147
|
{ title: 'Uploads', file: '/opt/arcubase-sdk/docs/runtime-reference/uploads.md' },
|
|
165
148
|
examplesIndexDocHint,
|
|
166
149
|
],
|
|
167
|
-
'user.
|
|
150
|
+
'user.workflow.queryEntity': [
|
|
168
151
|
{ title: 'Search and bulk actions', file: '/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md' },
|
|
169
152
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
170
153
|
examplesIndexDocHint,
|
|
171
154
|
],
|
|
172
|
-
'user.
|
|
155
|
+
'user.workflow.getEntityRow': [
|
|
173
156
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
174
157
|
examplesIndexDocHint,
|
|
175
158
|
],
|
|
176
|
-
'user.
|
|
159
|
+
'user.workflow.updateEntityRow': [
|
|
177
160
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
178
161
|
{ title: 'Uploads', file: '/opt/arcubase-sdk/docs/runtime-reference/uploads.md' },
|
|
179
162
|
examplesIndexDocHint,
|
|
180
163
|
],
|
|
181
|
-
'user.
|
|
164
|
+
'user.workflow.queryEntitySelection': [
|
|
182
165
|
{ title: 'Search and bulk actions', file: '/opt/arcubase-sdk/docs/runtime-reference/search-and-bulk-actions.md' },
|
|
183
166
|
examplesIndexDocHint,
|
|
184
167
|
],
|
|
185
|
-
'user.
|
|
168
|
+
'user.workflow.deleteEntityRow': [
|
|
186
169
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
187
170
|
examplesIndexDocHint,
|
|
188
171
|
],
|
|
189
|
-
'user.
|
|
172
|
+
'user.workflow.restoreEntityRow': [
|
|
190
173
|
{ title: 'Row CRUD', file: '/opt/arcubase-sdk/docs/runtime-reference/row-crud.md' },
|
|
191
174
|
examplesIndexDocHint,
|
|
192
175
|
],
|