contensis-cli 1.6.1-beta.13 → 1.6.1-beta.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/dist/index.js +200 -8
- package/dist/index.js.map +3 -3
- package/dist/shell.js +200 -8
- package/dist/shell.js.map +3 -3
- package/package.json +1 -1
- package/src/commands/create.ts +48 -0
- package/src/commands/set.ts +69 -1
- package/src/localisation/en-GB.ts +8 -0
- package/src/services/ContensisCliService.ts +150 -4
- package/src/shell.ts +6 -1
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contensis-cli",
|
|
3
|
-
"version": "1.6.1-beta.
|
|
3
|
+
"version": "1.6.1-beta.15",
|
|
4
4
|
"description": "A fully featured Contensis command line interface with a shell UI provides simple and intuitive ways to manage or profile your content in any NodeJS terminal.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
package/src/commands/create.ts
CHANGED
|
@@ -71,6 +71,54 @@ Example call:
|
|
|
71
71
|
);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
+
create
|
|
75
|
+
.command('node')
|
|
76
|
+
.description('create a new site view node')
|
|
77
|
+
.argument('<"node path or id">', 'the path or id of the node to create')
|
|
78
|
+
.argument(
|
|
79
|
+
'["display name"]',
|
|
80
|
+
'provide a separate display name for the node (optional)'
|
|
81
|
+
)
|
|
82
|
+
.argument(
|
|
83
|
+
'["slug"]',
|
|
84
|
+
'provide a slug for the node (defaults to slug from provided node path)'
|
|
85
|
+
)
|
|
86
|
+
.option(
|
|
87
|
+
'--include-in-menu',
|
|
88
|
+
'set include in menu flag on the created node',
|
|
89
|
+
false
|
|
90
|
+
)
|
|
91
|
+
.option(
|
|
92
|
+
'--language <language>',
|
|
93
|
+
'language of the node to create (defaults to current project primary language)'
|
|
94
|
+
)
|
|
95
|
+
.option('--entry-id <entryId>', 'attach an entry to the node')
|
|
96
|
+
.usage(
|
|
97
|
+
'<"node path or id"> ["display name"] (both args in "double quotes")'
|
|
98
|
+
)
|
|
99
|
+
.addHelpText(
|
|
100
|
+
'after',
|
|
101
|
+
`
|
|
102
|
+
Example call:
|
|
103
|
+
> create node /test "Test Node" --include-in-menu\n`
|
|
104
|
+
)
|
|
105
|
+
.action(
|
|
106
|
+
async (
|
|
107
|
+
pathOrId: string,
|
|
108
|
+
displayName: string,
|
|
109
|
+
slug: string,
|
|
110
|
+
opts: any
|
|
111
|
+
) => {
|
|
112
|
+
await cliCommand(['create', 'node', pathOrId], opts).CreateOrUpdateNode(
|
|
113
|
+
pathOrId,
|
|
114
|
+
opts,
|
|
115
|
+
displayName,
|
|
116
|
+
slug,
|
|
117
|
+
opts.language
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
|
|
74
122
|
create
|
|
75
123
|
.command('role')
|
|
76
124
|
.description('create a new role')
|
package/src/commands/set.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Argument, Command } from 'commander';
|
|
1
|
+
import { Argument, Command, Option } from 'commander';
|
|
2
2
|
import { cliCommand } from '~/services/ContensisCliService';
|
|
3
3
|
import { shell } from '~/shell';
|
|
4
4
|
|
|
@@ -10,6 +10,56 @@ export const makeSetCommand = () => {
|
|
|
10
10
|
.showHelpAfterError(true)
|
|
11
11
|
.exitOverride();
|
|
12
12
|
|
|
13
|
+
const node = set.command('node').description('update a site view node');
|
|
14
|
+
|
|
15
|
+
node
|
|
16
|
+
.command('entry')
|
|
17
|
+
.description('assign an entry to a node')
|
|
18
|
+
.argument('<"node path or id">', 'the path or id of the node to update')
|
|
19
|
+
.argument('<entryId>', 'the new entry id to assign to the node')
|
|
20
|
+
.usage('<"node path or id"> <entryId>')
|
|
21
|
+
.addHelpText(
|
|
22
|
+
'after',
|
|
23
|
+
`
|
|
24
|
+
Example call:
|
|
25
|
+
> set node entry /path 1502f64e-e9b1-436b-b62f-e273f639ecb6\n`
|
|
26
|
+
)
|
|
27
|
+
.action(async (nodePathOrId: string, entryId: string, opts) => {
|
|
28
|
+
await cliCommand(['set', 'node', 'entry'], opts).CreateOrUpdateNode(
|
|
29
|
+
nodePathOrId,
|
|
30
|
+
{ entryId }
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
node
|
|
35
|
+
.command('renderer')
|
|
36
|
+
.description('assign a renderer to a node')
|
|
37
|
+
.argument('<"node path or id">', 'the path or id of the node to update')
|
|
38
|
+
.argument('<rendererUuid>', 'the renderer uuid to assign to the node')
|
|
39
|
+
.option(
|
|
40
|
+
'--is-partial-match-root',
|
|
41
|
+
'should the renderer be used as the partial match root for the node',
|
|
42
|
+
false
|
|
43
|
+
)
|
|
44
|
+
.usage('<"node path or id"> <rendererUuid>')
|
|
45
|
+
.addHelpText(
|
|
46
|
+
'after',
|
|
47
|
+
`
|
|
48
|
+
Example call:
|
|
49
|
+
> set node renderer /path 1502f64e-e9b1-436b-b62f-e273f639ecb6 --is-partial-match-root\n`
|
|
50
|
+
)
|
|
51
|
+
.action(async (nodePathOrId: string, rendererId: string, opts) => {
|
|
52
|
+
await cliCommand(['set', 'node', 'renderer'], opts).CreateOrUpdateNode(
|
|
53
|
+
nodePathOrId,
|
|
54
|
+
{
|
|
55
|
+
renderer: {
|
|
56
|
+
id: rendererId,
|
|
57
|
+
isPartialMatchRoot: opts.isPartialMatchRoot,
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
13
63
|
const project = set
|
|
14
64
|
.command('project')
|
|
15
65
|
.description('set current working project')
|
|
@@ -178,6 +228,21 @@ Example call:
|
|
|
178
228
|
'--entry-languages [entry-languages...]',
|
|
179
229
|
'the entry languages to add to the role permissions'
|
|
180
230
|
)
|
|
231
|
+
.addOption(
|
|
232
|
+
new Option(
|
|
233
|
+
'--block-actions [block-actions...]',
|
|
234
|
+
'the block actions to add to the role permissions'
|
|
235
|
+
).choices([
|
|
236
|
+
'push',
|
|
237
|
+
'release',
|
|
238
|
+
'manageLive',
|
|
239
|
+
'manualStartStop',
|
|
240
|
+
'markAsBroken',
|
|
241
|
+
'delete',
|
|
242
|
+
'view',
|
|
243
|
+
'*',
|
|
244
|
+
])
|
|
245
|
+
)
|
|
181
246
|
.addHelpText(
|
|
182
247
|
'after',
|
|
183
248
|
`
|
|
@@ -194,6 +259,9 @@ Example call:
|
|
|
194
259
|
actions: opts.entryActions || [],
|
|
195
260
|
languages: opts.entryLanguages || [],
|
|
196
261
|
})),
|
|
262
|
+
blocks: opts.blockActions
|
|
263
|
+
? { actions: opts.blockActions }
|
|
264
|
+
: undefined,
|
|
197
265
|
},
|
|
198
266
|
}
|
|
199
267
|
);
|
|
@@ -188,6 +188,14 @@ export const LogMessages = {
|
|
|
188
188
|
depth ? ` to a depth of ${depth}` : ``
|
|
189
189
|
}\n`,
|
|
190
190
|
noChange: (env: string) => `[${env}] No changes to be made`,
|
|
191
|
+
setPayload: () => `Updating node with details\n`,
|
|
192
|
+
set: (env: string) => `[${env}] Succesfully updated node\n`,
|
|
193
|
+
failedSet: (env: string, name?: string) =>
|
|
194
|
+
`[${env}] Unable to update node ${Logger.highlightText(name)}`,
|
|
195
|
+
created: (env: string, name: string) =>
|
|
196
|
+
`[${env}] Created node ${Logger.highlightText(name)}\n`,
|
|
197
|
+
failedCreate: (env: string, name?: string) =>
|
|
198
|
+
`[${env}] Unable to create node ${Logger.highlightText(name)}`,
|
|
191
199
|
},
|
|
192
200
|
contenttypes: {
|
|
193
201
|
list: (projectId: string) =>
|
|
@@ -8,8 +8,10 @@ import clone from 'rfdc';
|
|
|
8
8
|
|
|
9
9
|
import { Component, ContentType, Project } from 'contensis-core-api';
|
|
10
10
|
import {
|
|
11
|
+
ICreateNode,
|
|
11
12
|
ICreateTag,
|
|
12
13
|
ICreateTagGroup,
|
|
14
|
+
Node,
|
|
13
15
|
Role,
|
|
14
16
|
Tag,
|
|
15
17
|
TagGroup,
|
|
@@ -23,6 +25,7 @@ import {
|
|
|
23
25
|
Model,
|
|
24
26
|
BlockActionType,
|
|
25
27
|
logEntitiesTable,
|
|
28
|
+
Renderer,
|
|
26
29
|
} from 'migratortron';
|
|
27
30
|
|
|
28
31
|
import ContensisAuthService from './ContensisAuthService';
|
|
@@ -2774,6 +2777,142 @@ class ContensisCli {
|
|
|
2774
2777
|
}
|
|
2775
2778
|
};
|
|
2776
2779
|
|
|
2780
|
+
CreateOrUpdateNode = async (
|
|
2781
|
+
nodePathOrId: string,
|
|
2782
|
+
nodeUpdates: Partial<Node>,
|
|
2783
|
+
displayName?: string | undefined,
|
|
2784
|
+
slug?: string | undefined,
|
|
2785
|
+
language?: string | undefined
|
|
2786
|
+
) => {
|
|
2787
|
+
const { currentEnv, currentProject, log, messages } = this;
|
|
2788
|
+
const contensis = await this.ConnectContensis();
|
|
2789
|
+
|
|
2790
|
+
const nodePath = nodePathOrId.startsWith('/') ? nodePathOrId : undefined;
|
|
2791
|
+
let nodeId = isUuid(nodePathOrId) ? nodePathOrId : undefined;
|
|
2792
|
+
|
|
2793
|
+
let existingNode: Node | undefined;
|
|
2794
|
+
let parentNode: Node | undefined;
|
|
2795
|
+
let updateNode: Node | undefined;
|
|
2796
|
+
|
|
2797
|
+
if (contensis) {
|
|
2798
|
+
// Retrieve node
|
|
2799
|
+
if (nodePath) {
|
|
2800
|
+
const [, nodesByPath] = await to(contensis.nodes.GetNodes(nodePath, 0));
|
|
2801
|
+
|
|
2802
|
+
if (Array.isArray(nodesByPath) && nodesByPath[0]?.id) {
|
|
2803
|
+
nodeId = nodesByPath[0].id;
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
if (nodeId) {
|
|
2808
|
+
// Get the management node so we can update it
|
|
2809
|
+
const [, nodeById] = await to(
|
|
2810
|
+
contensis.source.repo.GetNodeById(nodeId)
|
|
2811
|
+
);
|
|
2812
|
+
|
|
2813
|
+
if (nodeById) existingNode = nodeById;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
// TODO: resolve any renderer id to its uuid so we can support passing the regular id for ease of use
|
|
2817
|
+
if (!existingNode) {
|
|
2818
|
+
// Build a node object to create or reject if there is not enough data
|
|
2819
|
+
|
|
2820
|
+
if (!language) {
|
|
2821
|
+
const project =
|
|
2822
|
+
await contensis.source.repo.GetProject(currentProject);
|
|
2823
|
+
language = project?.primaryLanguage || 'en-GB';
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
if (!nodeUpdates.parentId) {
|
|
2827
|
+
// Find the node's parentId from the path if possible
|
|
2828
|
+
if (!nodePath)
|
|
2829
|
+
throw new Error(
|
|
2830
|
+
`A node with id "${nodeId}" does not exist, and a path was not provided to find the parent node.`
|
|
2831
|
+
);
|
|
2832
|
+
|
|
2833
|
+
const parentPath =
|
|
2834
|
+
nodePath.substring(0, nodePath.lastIndexOf('/')) || '/';
|
|
2835
|
+
const [, parentNodesByPath] = await to(
|
|
2836
|
+
contensis.nodes.GetNodes(parentPath, 0)
|
|
2837
|
+
);
|
|
2838
|
+
|
|
2839
|
+
if (!parentNodesByPath?.[0]?.id)
|
|
2840
|
+
throw new Error(
|
|
2841
|
+
`A node with id "${nodeId}" does not exist, and the parent node could not be found at path "${parentPath}".`
|
|
2842
|
+
);
|
|
2843
|
+
else parentNode = parentNodesByPath[0] as unknown as Node;
|
|
2844
|
+
}
|
|
2845
|
+
const pathSlug = nodePath?.substring(nodePath.lastIndexOf('/') + 1);
|
|
2846
|
+
|
|
2847
|
+
const createNode: ICreateNode = {
|
|
2848
|
+
id: nodeId,
|
|
2849
|
+
parentId: nodeUpdates.parentId || parentNode?.id,
|
|
2850
|
+
projectId: currentProject,
|
|
2851
|
+
displayName: displayName
|
|
2852
|
+
? {
|
|
2853
|
+
[language]: displayName,
|
|
2854
|
+
}
|
|
2855
|
+
: nodeUpdates.displayName
|
|
2856
|
+
? nodeUpdates.displayName
|
|
2857
|
+
: pathSlug
|
|
2858
|
+
? {
|
|
2859
|
+
[language]: pathSlug,
|
|
2860
|
+
}
|
|
2861
|
+
: (undefined as any),
|
|
2862
|
+
slug: slug
|
|
2863
|
+
? {
|
|
2864
|
+
[language]: slug,
|
|
2865
|
+
}
|
|
2866
|
+
: nodeUpdates.slug
|
|
2867
|
+
? nodeUpdates.slug
|
|
2868
|
+
: pathSlug
|
|
2869
|
+
? {
|
|
2870
|
+
[language]: pathSlug,
|
|
2871
|
+
}
|
|
2872
|
+
: (undefined as any),
|
|
2873
|
+
entryId: nodeUpdates.entryId,
|
|
2874
|
+
isCanonical: nodeUpdates.isCanonical,
|
|
2875
|
+
renderer: nodeUpdates.renderer,
|
|
2876
|
+
proxy: nodeUpdates.proxy,
|
|
2877
|
+
includeInMenu: nodeUpdates.includeInMenu,
|
|
2878
|
+
};
|
|
2879
|
+
|
|
2880
|
+
// Validate createNode
|
|
2881
|
+
updateNode = createNode as Node;
|
|
2882
|
+
} else {
|
|
2883
|
+
updateNode = { ...existingNode, ...nodeUpdates };
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
if (updateNode) {
|
|
2887
|
+
log.info(messages.nodes.setPayload());
|
|
2888
|
+
log.object(updateNode);
|
|
2889
|
+
const [err, newNode] = await contensis.source.repo.UpdateOrCreateNode(
|
|
2890
|
+
existingNode as Node,
|
|
2891
|
+
updateNode
|
|
2892
|
+
);
|
|
2893
|
+
|
|
2894
|
+
if (err)
|
|
2895
|
+
log.error(
|
|
2896
|
+
messages.nodes[existingNode ? 'failedSet' : 'failedCreate'](
|
|
2897
|
+
currentEnv,
|
|
2898
|
+
nodePathOrId
|
|
2899
|
+
),
|
|
2900
|
+
err
|
|
2901
|
+
);
|
|
2902
|
+
else if (newNode) {
|
|
2903
|
+
log.success(
|
|
2904
|
+
messages.nodes[existingNode ? 'set' : 'created'](
|
|
2905
|
+
currentEnv,
|
|
2906
|
+
newNode.id
|
|
2907
|
+
)
|
|
2908
|
+
);
|
|
2909
|
+
|
|
2910
|
+
await this.HandleFormattingAndOutput(newNode, log.object);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
};
|
|
2915
|
+
|
|
2777
2916
|
PrintWebhookSubscriptions = async (subscriptionIdsOrNames?: string[]) => {
|
|
2778
2917
|
const { currentEnv, log, messages } = this;
|
|
2779
2918
|
const contensis = await this.ConnectContensis();
|
|
@@ -3372,7 +3511,6 @@ class ContensisCli {
|
|
|
3372
3511
|
}
|
|
3373
3512
|
};
|
|
3374
3513
|
|
|
3375
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3376
3514
|
PrintRenderers = async (rendererId?: string) => {
|
|
3377
3515
|
const { currentEnv, env, log, messages } = this;
|
|
3378
3516
|
const contensis = await this.ConnectContensis();
|
|
@@ -3381,19 +3519,27 @@ class ContensisCli {
|
|
|
3381
3519
|
const [err, renderers] = await contensis.renderers.GetRenderers();
|
|
3382
3520
|
|
|
3383
3521
|
if (Array.isArray(renderers)) {
|
|
3384
|
-
|
|
3522
|
+
const result = rendererId
|
|
3523
|
+
? ([renderers.find(r => r.id === rendererId)].filter(
|
|
3524
|
+
Boolean
|
|
3525
|
+
) as Renderer[])
|
|
3526
|
+
: renderers || [];
|
|
3527
|
+
|
|
3528
|
+
await this.HandleFormattingAndOutput(result, () => {
|
|
3385
3529
|
// print the renderers to console
|
|
3386
3530
|
log.success(messages.renderers.list(currentEnv, env.currentProject));
|
|
3387
3531
|
for (const {
|
|
3532
|
+
uuid,
|
|
3388
3533
|
id,
|
|
3389
3534
|
description,
|
|
3390
3535
|
assignedContentTypes,
|
|
3391
3536
|
rules,
|
|
3392
3537
|
version,
|
|
3393
|
-
} of
|
|
3538
|
+
} of result) {
|
|
3394
3539
|
console.log(
|
|
3395
3540
|
` - ${id} [${version.versionNo}] ${log.infoText`${description}`}`
|
|
3396
3541
|
);
|
|
3542
|
+
console.log(log.infoText` uuid: ${uuid}`);
|
|
3397
3543
|
if (assignedContentTypes?.length)
|
|
3398
3544
|
console.log(
|
|
3399
3545
|
log.infoText` assignedContentTypes: ${assignedContentTypes.join(
|
|
@@ -3409,7 +3555,7 @@ class ContensisCli {
|
|
|
3409
3555
|
);
|
|
3410
3556
|
}
|
|
3411
3557
|
});
|
|
3412
|
-
return
|
|
3558
|
+
return result;
|
|
3413
3559
|
}
|
|
3414
3560
|
|
|
3415
3561
|
if (err) {
|
package/src/shell.ts
CHANGED
|
@@ -142,12 +142,15 @@ class ContensisShell {
|
|
|
142
142
|
'login',
|
|
143
143
|
'list projects',
|
|
144
144
|
'set project',
|
|
145
|
-
...(this.env?.projects || []).map(
|
|
145
|
+
...(this.env?.projects || []).map(
|
|
146
|
+
project => `set project ${project.id}`
|
|
147
|
+
)
|
|
146
148
|
);
|
|
147
149
|
if (userId)
|
|
148
150
|
availableCommands.push(
|
|
149
151
|
'copy field',
|
|
150
152
|
'create key',
|
|
153
|
+
'create node',
|
|
151
154
|
'create project',
|
|
152
155
|
'create role',
|
|
153
156
|
'create tag',
|
|
@@ -208,6 +211,8 @@ class ContensisShell {
|
|
|
208
211
|
'remove tags',
|
|
209
212
|
'remove tags in',
|
|
210
213
|
'remove taggroup',
|
|
214
|
+
'set node entry',
|
|
215
|
+
'set node renderer',
|
|
211
216
|
'set project name',
|
|
212
217
|
'set project description',
|
|
213
218
|
'set role name',
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LIB_VERSION = "1.6.1-beta.
|
|
1
|
+
export const LIB_VERSION = "1.6.1-beta.15";
|