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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contensis-cli",
3
- "version": "1.6.1-beta.13",
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",
@@ -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')
@@ -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
- await this.HandleFormattingAndOutput(renderers, () => {
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 renderers) {
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 renderers;
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(project => `set project ${project.id}`)
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.13";
1
+ export const LIB_VERSION = "1.6.1-beta.15";