@contrail/cli 3.5.4 → 3.5.5-alpha.177136f

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 (30) hide show
  1. package/README.md +50 -1
  2. package/dist/api/feature-flags.d.ts +3 -0
  3. package/dist/api/feature-flags.js +29 -0
  4. package/dist/api/users.d.ts +1 -0
  5. package/dist/api/users.js +10 -1
  6. package/dist/commands/feature-flags/export.d.ts +19 -0
  7. package/dist/commands/feature-flags/export.js +66 -0
  8. package/dist/commands/feature-flags/export.spec.d.ts +1 -0
  9. package/dist/commands/feature-flags/export.spec.js +109 -0
  10. package/dist/commands/feature-flags/import.d.ts +42 -0
  11. package/dist/commands/feature-flags/import.js +191 -0
  12. package/dist/commands/feature-flags/import.spec.d.ts +1 -0
  13. package/dist/commands/feature-flags/import.spec.js +194 -0
  14. package/dist/commands/instance/export.d.ts +9 -0
  15. package/dist/commands/instance/export.js +18 -3
  16. package/dist/commands/instance/export.spec.d.ts +1 -0
  17. package/dist/commands/instance/export.spec.js +32 -0
  18. package/dist/commands/instance/import.d.ts +3 -0
  19. package/dist/commands/instance/import.js +5 -0
  20. package/dist/commands/instance/import.spec.js +4 -0
  21. package/dist/helpers/app/app-config-validators.d.ts +5 -0
  22. package/dist/helpers/app/app-config-validators.js +102 -3
  23. package/dist/helpers/app/app-config-validators.spec.js +46 -0
  24. package/dist/helpers/app/extensions-deployer.d.ts +10 -2
  25. package/dist/helpers/app/extensions-deployer.js +31 -37
  26. package/dist/helpers/app/extensions-deployer.spec.d.ts +1 -0
  27. package/dist/helpers/app/extensions-deployer.spec.js +29 -0
  28. package/dist/interfaces.d.ts +36 -0
  29. package/oclif.manifest.json +111 -1
  30. package/package.json +4 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExtensionsDeployer = exports.getExtensionDefinitionsForAppVersion = void 0;
3
+ exports.ExtensionsDeployer = exports.buildExtensionDefinition = exports.getExtensionDefinitionsForAppVersion = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const sdk_1 = require("@contrail/sdk");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
@@ -13,6 +13,28 @@ async function getExtensionDefinitionsForAppVersion(app) {
13
13
  });
14
14
  }
15
15
  exports.getExtensionDefinitionsForAppVersion = getExtensionDefinitionsForAppVersion;
16
+ /** The definition published for an app.yml extension, for a new version or an update alike. */
17
+ function buildExtensionDefinition(extension, app, appName) {
18
+ return {
19
+ identifier: util_1.AppUtil.createExtensionIdentifier({
20
+ extensionIdentifier: extension?.identifier,
21
+ appIdentifier: app.identifier,
22
+ }),
23
+ name: extension.name,
24
+ appId: app.id,
25
+ appVersionId: app.latestAppVersionId,
26
+ extensionType: extension.extensionType,
27
+ userApps: extension.userApps,
28
+ /** @deprecated since entity-types v1.5.1, use display instead */
29
+ modalDimensions: extension.modalDimensions,
30
+ display: extension.display,
31
+ iframeUrl: extension.iframeUrl,
32
+ icon: extension.icon,
33
+ appliesTo: extension.appliesTo,
34
+ group: extension.group ?? appName,
35
+ };
36
+ }
37
+ exports.buildExtensionDefinition = buildExtensionDefinition;
16
38
  class ExtensionsDeployer {
17
39
  async deployExtensions(appDeclaration, app) {
18
40
  // FETCH ALL EXTENSIONS FROM THE API.
@@ -26,11 +48,11 @@ class ExtensionsDeployer {
26
48
  logger_1.default.debug(appDeclaration.extensions);
27
49
  if (appDeclaration.extensions) {
28
50
  for (const extension of appDeclaration?.extensions ?? []) {
29
- await this.deployExtension(extension, app, existingExtensions);
51
+ await this.deployExtension(extension, app, existingExtensions, appDeclaration.appName);
30
52
  }
31
53
  }
32
54
  }
33
- async deployExtension(extension, app, existingExtensions) {
55
+ async deployExtension(extension, app, existingExtensions, appName) {
34
56
  logger_1.default.info(`${chalk_1.default.yellow.bold('EXTENSION')} \tDeploying extension: ${extension?.identifier}`);
35
57
  const identifier = util_1.AppUtil.createExtensionIdentifier({
36
58
  appIdentifier: app.identifier,
@@ -38,28 +60,14 @@ class ExtensionsDeployer {
38
60
  });
39
61
  const existingDefinition = existingExtensions.find((ad) => ad.identifier === identifier);
40
62
  if (!existingDefinition) {
41
- await this.createNewExtensionDefinition(extension, app);
63
+ await this.createNewExtensionDefinition(extension, app, appName);
42
64
  }
43
65
  else {
44
- await this.updateActionDefinition(existingDefinition, extension, app);
66
+ await this.updateActionDefinition(existingDefinition, extension, app, appName);
45
67
  }
46
68
  }
47
- async createNewExtensionDefinition(extension, app) {
48
- const newObject = {
49
- identifier: util_1.AppUtil.createExtensionIdentifier({
50
- extensionIdentifier: extension?.identifier,
51
- appIdentifier: app.identifier,
52
- }),
53
- name: extension.name,
54
- appId: app.id,
55
- appVersionId: app.latestAppVersionId,
56
- extensionType: extension.extensionType,
57
- userApps: extension.userApps,
58
- /** @deprecated since entity-types v1.5.1, use display instead */
59
- modalDimensions: extension.modalDimensions,
60
- display: extension.display,
61
- iframeUrl: extension.iframeUrl,
62
- };
69
+ async createNewExtensionDefinition(extension, app, appName) {
70
+ const newObject = buildExtensionDefinition(extension, app, appName);
63
71
  const actionDefinition = await new sdk_1.Entities().create({
64
72
  entityName: 'app-extension-definition',
65
73
  object: newObject,
@@ -67,22 +75,8 @@ class ExtensionsDeployer {
67
75
  logger_1.default.info(`${chalk_1.default.yellow.bold('EXTENSION')} Created new extension definition: ${extension?.identifier}`);
68
76
  return actionDefinition;
69
77
  }
70
- async updateActionDefinition(existingActionDefinition, extension, app) {
71
- const updates = {
72
- identifier: util_1.AppUtil.createExtensionIdentifier({
73
- extensionIdentifier: extension?.identifier,
74
- appIdentifier: app.identifier,
75
- }),
76
- name: extension.name,
77
- appId: app.id,
78
- appVersionId: app.latestAppVersionId,
79
- extensionType: extension.extensionType,
80
- userApps: extension.userApps,
81
- /** @deprecated since entity-types v1.5.1, use display instead */
82
- modalDimensions: extension.modalDimensions,
83
- display: extension.display,
84
- iframeUrl: extension.iframeUrl,
85
- };
78
+ async updateActionDefinition(existingActionDefinition, extension, app, appName) {
79
+ const updates = buildExtensionDefinition(extension, app, appName);
86
80
  const extensionDefinition = await new sdk_1.Entities().update({
87
81
  entityName: 'app-extension-definition',
88
82
  id: existingActionDefinition.id,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const extensions_deployer_1 = require("./extensions-deployer");
4
+ const app = {
5
+ id: 'app-1',
6
+ identifier: '@vibeiq.com/gap-design-poc',
7
+ latestAppVersionId: 'version-1',
8
+ };
9
+ describe('buildExtensionDefinition', () => {
10
+ it('should publish placement as declared, grouped under the app name', () => {
11
+ const definition = (0, extensions_deployer_1.buildExtensionDefinition)({
12
+ identifier: 'line-builder',
13
+ name: 'Line builder',
14
+ iframeUrl: 'http://localhost:4395/index.html#/line-builder',
15
+ icon: 'line-builder',
16
+ appliesTo: { typePaths: ['custom-entity:silhouette'], maxSelected: 20 },
17
+ }, app, 'Gap');
18
+ expect(definition).toMatchObject({
19
+ identifier: '@vibeiq.com/gap-design-poc:line-builder',
20
+ appVersionId: 'version-1',
21
+ icon: 'line-builder',
22
+ appliesTo: { typePaths: ['custom-entity:silhouette'], maxSelected: 20 },
23
+ group: 'Gap',
24
+ });
25
+ });
26
+ it("should keep an extension's own group", () => {
27
+ expect((0, extensions_deployer_1.buildExtensionDefinition)({ identifier: 'x', name: 'X', group: 'Tools' }, app, 'Gap').group).toBe('Tools');
28
+ });
29
+ });
@@ -55,6 +55,42 @@ export interface ExtensionDefinitionDeclaration {
55
55
  modalDimensions?: any;
56
56
  display?: AppExtensionDisplayConfiguration;
57
57
  iframeUrl?: string;
58
+ /** A default icon's name, `{ material: <icon name> }`, or `{ url: <one-color SVG, absolute or beside iframeUrl> }`.
59
+ * An extension without an icon shows none. */
60
+ icon?: ExtensionIconDeclaration;
61
+ /** What the extension acts on. Apps offer it beside a selection it fits (Boards: the property bar's app row and the
62
+ * top of the context menu); without it, it is offered as before. */
63
+ appliesTo?: ExtensionAppliesToDeclaration;
64
+ /** The name the app's extensions are grouped under; defaults to appName. */
65
+ group?: string;
66
+ }
67
+ export type ExtensionIconDeclaration = string | {
68
+ material: string;
69
+ } | {
70
+ url: string;
71
+ };
72
+ /** Which selected records a rule takes: by type path (with subtypes), exclusions, item role and how many. */
73
+ export interface ExtensionSelectionRuleDeclaration {
74
+ /** Type paths, each matching itself and its subtypes: item:product matches item:product:footwear. */
75
+ typePaths?: string[];
76
+ /** Type paths left out, with their subtypes: item:material. */
77
+ excludeTypePaths?: string[];
78
+ /** Item roles a record must have: family, option. */
79
+ roles?: string[];
80
+ /** Fewest records: 1 for a target, 0 for an input, unless set. */
81
+ minSelected?: number;
82
+ maxSelected?: number;
83
+ /** What to select, for hints and summaries: "a Design or BOM", "colors". */
84
+ label?: string;
85
+ }
86
+ /**
87
+ * A selection is a target (what the action acts on) plus optional inputs that come along with it (colors to build
88
+ * in). Every selected record must fit the target or an input. The flat form, the rule's fields with no target, is a
89
+ * target with no inputs.
90
+ */
91
+ export interface ExtensionAppliesToDeclaration extends ExtensionSelectionRuleDeclaration {
92
+ target?: ExtensionSelectionRuleDeclaration;
93
+ inputs?: ExtensionSelectionRuleDeclaration[];
58
94
  }
59
95
  export interface ConfigPropertyElements {
60
96
  [key: string]: ConfigPropertyElement;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.5.4",
2
+ "version": "3.5.5-alpha.177136f",
3
3
  "commands": {
4
4
  "app:create": {
5
5
  "id": "app:create",
@@ -672,6 +672,116 @@
672
672
  }
673
673
  }
674
674
  },
675
+ "feature-flags:export": {
676
+ "id": "feature-flags:export",
677
+ "description": "Export the enabled feature flags for your Org",
678
+ "strict": true,
679
+ "pluginName": "@contrail/cli",
680
+ "pluginAlias": "@contrail/cli",
681
+ "pluginType": "core",
682
+ "aliases": [],
683
+ "examples": [
684
+ "$ contrail feature-flags export\n"
685
+ ],
686
+ "flags": {
687
+ "logLevel": {
688
+ "name": "logLevel",
689
+ "type": "option",
690
+ "char": "l",
691
+ "description": "The Log Level",
692
+ "required": false,
693
+ "multiple": false,
694
+ "options": [
695
+ "error",
696
+ "warn",
697
+ "info",
698
+ "debug"
699
+ ]
700
+ },
701
+ "alwaysConfirmEnv": {
702
+ "name": "alwaysConfirmEnv",
703
+ "type": "option",
704
+ "char": "e",
705
+ "description": "The Environment variables",
706
+ "required": false,
707
+ "multiple": false,
708
+ "options": [
709
+ "true",
710
+ "false"
711
+ ],
712
+ "default": "true"
713
+ },
714
+ "outDir": {
715
+ "name": "outDir",
716
+ "type": "option",
717
+ "char": "d",
718
+ "description": "The directory to which to export the feature flags. Defaults to the current directory",
719
+ "required": false,
720
+ "multiple": false,
721
+ "default": "."
722
+ },
723
+ "overwrite": {
724
+ "name": "overwrite",
725
+ "type": "boolean",
726
+ "char": "f",
727
+ "description": "Replaces any existing export files in outDir",
728
+ "required": false,
729
+ "allowNo": false
730
+ }
731
+ },
732
+ "args": {}
733
+ },
734
+ "feature-flags:import": {
735
+ "id": "feature-flags:import",
736
+ "description": "Upload an extracted set of feature flags",
737
+ "strict": true,
738
+ "pluginName": "@contrail/cli",
739
+ "pluginAlias": "@contrail/cli",
740
+ "pluginType": "core",
741
+ "aliases": [],
742
+ "examples": [
743
+ "$ contrail feature-flags import\n"
744
+ ],
745
+ "flags": {
746
+ "logLevel": {
747
+ "name": "logLevel",
748
+ "type": "option",
749
+ "char": "l",
750
+ "description": "The Log Level",
751
+ "required": false,
752
+ "multiple": false,
753
+ "options": [
754
+ "error",
755
+ "warn",
756
+ "info",
757
+ "debug"
758
+ ]
759
+ },
760
+ "alwaysConfirmEnv": {
761
+ "name": "alwaysConfirmEnv",
762
+ "type": "option",
763
+ "char": "e",
764
+ "description": "The Environment variables",
765
+ "required": false,
766
+ "multiple": false,
767
+ "options": [
768
+ "true",
769
+ "false"
770
+ ],
771
+ "default": "true"
772
+ },
773
+ "dir": {
774
+ "name": "dir",
775
+ "type": "option",
776
+ "char": "d",
777
+ "description": "The directory from which to import the feature flags. Defaults to the current directory. The feature flags will be loaded from $dir/feature-flags.yml",
778
+ "required": false,
779
+ "multiple": false,
780
+ "default": "."
781
+ }
782
+ },
783
+ "args": {}
784
+ },
675
785
  "file:upload": {
676
786
  "id": "file:upload",
677
787
  "description": "Uploads a file to the VibeIQ platform",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/cli",
3
- "version": "3.5.4",
3
+ "version": "3.5.5-alpha.177136f",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "bin": {
6
6
  "contrail-cli": "./bin/run",
@@ -116,6 +116,9 @@
116
116
  "org-config": {
117
117
  "description": "Export and import org-level configuration"
118
118
  },
119
+ "feature-flags": {
120
+ "description": "Export and import the org's enabled feature flags"
121
+ },
119
122
  "webhooks": {
120
123
  "description": "Manage VibeIQ webhooks"
121
124
  },