@contrail/flexplm 1.4.0 → 1.5.0-alpha.14a4f1b

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 (112) hide show
  1. package/lib/cli/commands/compile.d.ts +4 -0
  2. package/lib/cli/commands/compile.js +73 -0
  3. package/lib/cli/commands/compile.spec.d.ts +1 -0
  4. package/lib/cli/commands/compile.spec.js +80 -0
  5. package/lib/cli/commands/create.d.ts +5 -0
  6. package/lib/cli/commands/create.js +77 -0
  7. package/lib/cli/commands/create.spec.d.ts +1 -0
  8. package/lib/cli/commands/create.spec.js +78 -0
  9. package/lib/cli/commands/upload.d.ts +17 -0
  10. package/lib/cli/commands/upload.js +228 -0
  11. package/lib/cli/commands/upload.spec.d.ts +1 -0
  12. package/lib/cli/commands/upload.spec.js +88 -0
  13. package/lib/cli/index.d.ts +5 -0
  14. package/lib/cli/index.js +70 -0
  15. package/lib/cli/index.spec.d.ts +1 -0
  16. package/lib/cli/index.spec.js +85 -0
  17. package/lib/cli/template/mapping-template.ts.template +62 -0
  18. package/lib/entity-processor/base-entity-processor.d.ts +65 -0
  19. package/lib/entity-processor/base-entity-processor.js +71 -0
  20. package/lib/entity-processor/base-entity-processor.spec.js +1 -0
  21. package/lib/index.d.ts +1 -0
  22. package/lib/index.js +1 -0
  23. package/lib/interfaces/mapping-file.d.ts +460 -0
  24. package/lib/interfaces/mapping-file.js +2 -0
  25. package/lib/publish/base-process-publish-assortment.d.ts +25 -0
  26. package/lib/publish/base-process-publish-assortment.js +60 -6
  27. package/lib/publish/base-process-publish-assortment.spec.js +22 -4
  28. package/lib/publish/mockData.js +5 -0
  29. package/lib/transform/identifier-conversion-spec-mockData.js +34 -6
  30. package/lib/transform/identifier-conversion.d.ts +36 -0
  31. package/lib/transform/identifier-conversion.js +37 -1
  32. package/lib/transform/identifier-conversion.spec.js +35 -0
  33. package/lib/util/config-defaults.d.ts +18 -0
  34. package/lib/util/config-defaults.js +25 -15
  35. package/lib/util/config-defaults.spec.js +56 -0
  36. package/lib/util/data-converter-spec-mockData.js +17 -3
  37. package/lib/util/data-converter.d.ts +102 -0
  38. package/lib/util/data-converter.js +195 -34
  39. package/lib/util/data-converter.spec.js +430 -0
  40. package/lib/util/error-response-object.d.ts +5 -0
  41. package/lib/util/error-response-object.js +7 -0
  42. package/lib/util/event-short-message-status.js +1 -0
  43. package/lib/util/federation.js +8 -0
  44. package/lib/util/flexplm-connect.d.ts +7 -0
  45. package/lib/util/flexplm-connect.js +14 -0
  46. package/lib/util/logger-config.js +1 -0
  47. package/lib/util/map-util-spec-mockData.js +17 -3
  48. package/lib/util/map-utils.d.ts +27 -0
  49. package/lib/util/map-utils.js +27 -0
  50. package/lib/util/thumbnail-util.d.ts +21 -0
  51. package/lib/util/thumbnail-util.js +28 -1
  52. package/lib/util/thumbnail-util.spec.js +6 -0
  53. package/lib/util/type-conversion-utils-spec-mockData.js +3 -3
  54. package/lib/util/type-conversion-utils.d.ts +151 -0
  55. package/lib/util/type-conversion-utils.js +154 -0
  56. package/lib/util/type-defaults.d.ts +69 -0
  57. package/lib/util/type-defaults.js +98 -4
  58. package/lib/util/type-defaults.spec.js +114 -4
  59. package/lib/util/type-utils.d.ts +21 -0
  60. package/lib/util/type-utils.js +23 -0
  61. package/lib/util/type-utils.spec.js +2 -0
  62. package/package.json +21 -6
  63. package/scripts/copy-template.js +10 -0
  64. package/.github/pull_request_template.md +0 -31
  65. package/.github/workflows/flexplm-lib.yml +0 -27
  66. package/.github/workflows/publish-to-npm.yml +0 -121
  67. package/CHANGELOG.md +0 -40
  68. package/publish.bat +0 -5
  69. package/publish.sh +0 -5
  70. package/src/entity-processor/base-entity-processor.spec.ts +0 -689
  71. package/src/entity-processor/base-entity-processor.ts +0 -583
  72. package/src/flexplm-request.ts +0 -28
  73. package/src/flexplm-utils.spec.ts +0 -27
  74. package/src/flexplm-utils.ts +0 -29
  75. package/src/index.ts +0 -22
  76. package/src/interfaces/interfaces.ts +0 -122
  77. package/src/interfaces/item-family-changes.ts +0 -67
  78. package/src/interfaces/publish-change-data.ts +0 -43
  79. package/src/publish/base-process-publish-assortment-callback.ts +0 -50
  80. package/src/publish/base-process-publish-assortment.spec.ts +0 -1992
  81. package/src/publish/base-process-publish-assortment.ts +0 -1134
  82. package/src/publish/mockData.ts +0 -4561
  83. package/src/transform/identifier-conversion-spec-mockData.ts +0 -496
  84. package/src/transform/identifier-conversion.spec.ts +0 -354
  85. package/src/transform/identifier-conversion.ts +0 -282
  86. package/src/util/config-defaults.spec.ts +0 -392
  87. package/src/util/config-defaults.ts +0 -97
  88. package/src/util/data-converter-spec-mockData.ts +0 -231
  89. package/src/util/data-converter.spec.ts +0 -1120
  90. package/src/util/data-converter.ts +0 -766
  91. package/src/util/error-response-object.spec.ts +0 -116
  92. package/src/util/error-response-object.ts +0 -50
  93. package/src/util/event-short-message-status.ts +0 -22
  94. package/src/util/federation.ts +0 -172
  95. package/src/util/flexplm-connect.spec.ts +0 -132
  96. package/src/util/flexplm-connect.ts +0 -208
  97. package/src/util/logger-config.ts +0 -20
  98. package/src/util/map-util-spec-mockData.ts +0 -231
  99. package/src/util/map-utils.spec.ts +0 -103
  100. package/src/util/map-utils.ts +0 -41
  101. package/src/util/mockData.ts +0 -101
  102. package/src/util/thumbnail-util.spec.ts +0 -508
  103. package/src/util/thumbnail-util.ts +0 -272
  104. package/src/util/type-conversion-utils-spec-mockData.ts +0 -272
  105. package/src/util/type-conversion-utils.spec.ts +0 -1031
  106. package/src/util/type-conversion-utils.ts +0 -490
  107. package/src/util/type-defaults.spec.ts +0 -669
  108. package/src/util/type-defaults.ts +0 -281
  109. package/src/util/type-utils.spec.ts +0 -227
  110. package/src/util/type-utils.ts +0 -144
  111. package/tsconfig.json +0 -24
  112. package/tslint.json +0 -57
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.main = exports.Cli = void 0;
5
+ const create_1 = require("./commands/create");
6
+ const compile_1 = require("./commands/compile");
7
+ const upload_1 = require("./commands/upload");
8
+ const USAGE = `Usage: flexplm-mapping <command> [args]
9
+
10
+ Commands:
11
+ create Scaffold a new mapping .ts file in the current directory
12
+ compile <path.ts> Transpile a mapping .ts file to .js alongside it
13
+ upload <path.ts> [opts] Compile a mapping .ts file and upload the resulting .js to VibeIQ
14
+
15
+ Upload options:
16
+ -m <message> Git commit message (prompted if omitted)
17
+ -b <branch> Create a new git branch before committing
18
+ --skip-git Skip the post-upload git commit (default: commit)
19
+
20
+ Environment (upload):
21
+ CONTRAIL_CLI_EMAIL VibeIQ user email
22
+ CONTRAIL_CLI_PASSWORD VibeIQ user password
23
+ `;
24
+ class Cli {
25
+ async main() {
26
+ const [, , command, ...rest] = process.argv;
27
+ switch (command) {
28
+ case 'create':
29
+ await new create_1.CreateCommand().run();
30
+ return;
31
+ case 'compile':
32
+ if (!rest[0]) {
33
+ console.error('compile: missing <path.ts> argument');
34
+ console.error(USAGE);
35
+ process.exit(1);
36
+ }
37
+ await new compile_1.CompileCommand().run(rest[0]);
38
+ return;
39
+ case 'upload':
40
+ if (!rest[0]) {
41
+ console.error('upload: missing <path.ts> argument');
42
+ console.error(USAGE);
43
+ process.exit(1);
44
+ }
45
+ await new upload_1.UploadCommand().run(rest);
46
+ return;
47
+ case undefined:
48
+ case '-h':
49
+ case '--help':
50
+ case 'help':
51
+ console.log(USAGE);
52
+ return;
53
+ default:
54
+ console.error(`Unknown command: ${command}`);
55
+ console.error(USAGE);
56
+ process.exit(1);
57
+ }
58
+ }
59
+ }
60
+ exports.Cli = Cli;
61
+ function main() {
62
+ return new Cli().main();
63
+ }
64
+ exports.main = main;
65
+ if (require.main === module) {
66
+ main().catch((err) => {
67
+ console.error(err && err.message ? err.message : err);
68
+ process.exit(1);
69
+ });
70
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const createRunMock = jest.fn().mockResolvedValue(undefined);
4
+ const compileRunMock = jest.fn().mockResolvedValue(undefined);
5
+ const uploadRunMock = jest.fn().mockResolvedValue(undefined);
6
+ jest.mock('./commands/create', () => ({
7
+ CreateCommand: jest.fn().mockImplementation(() => ({ run: createRunMock })),
8
+ }));
9
+ jest.mock('./commands/compile', () => ({
10
+ CompileCommand: jest.fn().mockImplementation(() => ({ run: compileRunMock })),
11
+ }));
12
+ jest.mock('./commands/upload', () => ({
13
+ UploadCommand: jest.fn().mockImplementation(() => ({ run: uploadRunMock })),
14
+ }));
15
+ const index_1 = require("./index");
16
+ describe('cli main dispatcher', () => {
17
+ let originalArgv;
18
+ let logSpy;
19
+ let errorSpy;
20
+ let exitSpy;
21
+ beforeEach(() => {
22
+ originalArgv = process.argv;
23
+ createRunMock.mockClear();
24
+ compileRunMock.mockClear();
25
+ uploadRunMock.mockClear();
26
+ logSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
27
+ errorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
28
+ exitSpy = jest.spyOn(process, 'exit').mockImplementation(((code) => {
29
+ throw new Error(`__EXIT__:${code}`);
30
+ }));
31
+ });
32
+ afterEach(() => {
33
+ process.argv = originalArgv;
34
+ logSpy.mockRestore();
35
+ errorSpy.mockRestore();
36
+ exitSpy.mockRestore();
37
+ });
38
+ function setArgv(...args) {
39
+ process.argv = ['node', 'cli', ...args];
40
+ }
41
+ it('dispatches the create command', async () => {
42
+ setArgv('create');
43
+ await (0, index_1.main)();
44
+ expect(createRunMock).toHaveBeenCalledTimes(1);
45
+ expect(compileRunMock).not.toHaveBeenCalled();
46
+ expect(uploadRunMock).not.toHaveBeenCalled();
47
+ });
48
+ it('dispatches the compile command with its argument', async () => {
49
+ setArgv('compile', 'mapping.ts');
50
+ await (0, index_1.main)();
51
+ expect(compileRunMock).toHaveBeenCalledWith('mapping.ts');
52
+ });
53
+ it('exits when compile is missing its argument', async () => {
54
+ setArgv('compile');
55
+ await expect((0, index_1.main)()).rejects.toThrow('__EXIT__:1');
56
+ expect(compileRunMock).not.toHaveBeenCalled();
57
+ expect(errorSpy).toHaveBeenCalledWith(expect.stringMatching(/missing <path\.ts>/));
58
+ });
59
+ it('dispatches the upload command and forwards remaining args', async () => {
60
+ setArgv('upload', 'mapping.ts', '-m', 'msg', '--skip-git');
61
+ await (0, index_1.main)();
62
+ expect(uploadRunMock).toHaveBeenCalledWith(['mapping.ts', '-m', 'msg', '--skip-git']);
63
+ });
64
+ it('exits when upload is missing its argument', async () => {
65
+ setArgv('upload');
66
+ await expect((0, index_1.main)()).rejects.toThrow('__EXIT__:1');
67
+ expect(uploadRunMock).not.toHaveBeenCalled();
68
+ expect(errorSpy).toHaveBeenCalledWith(expect.stringMatching(/missing <path\.ts>/));
69
+ });
70
+ it.each(['help', '-h', '--help'])('prints usage for %s', async (helpFlag) => {
71
+ setArgv(helpFlag);
72
+ await (0, index_1.main)();
73
+ expect(logSpy).toHaveBeenCalledWith(expect.stringMatching(/Usage: flexplm-mapping/));
74
+ });
75
+ it('prints usage when no command is provided', async () => {
76
+ setArgv();
77
+ await (0, index_1.main)();
78
+ expect(logSpy).toHaveBeenCalledWith(expect.stringMatching(/Usage: flexplm-mapping/));
79
+ });
80
+ it('exits on an unknown command', async () => {
81
+ setArgv('bogus');
82
+ await expect((0, index_1.main)()).rejects.toThrow('__EXIT__:1');
83
+ expect(errorSpy).toHaveBeenCalledWith(expect.stringMatching(/Unknown command: bogus/));
84
+ });
85
+ });
@@ -0,0 +1,62 @@
1
+ import type { MappingFile } from '@contrail/flexplm';
2
+
3
+ export const mapping: MappingFile = {
4
+ orgInfo: {
5
+ appIdentifier: '@vibeiq/flexplm-connector',
6
+ orgName: '<ORG_NAME>',
7
+ },
8
+ typeConversion: {
9
+ vibe2flex: {},
10
+ flex2vibe: {},
11
+ },
12
+ LCSSeason: {
13
+ vibeOwningKeys: ['flexPLMSeasonName'],
14
+ vibe2flex: {
15
+ transformOrder: [{ processor: 'REKEY', rekeyDelete: true, rekeyTransformersKey: 'rekey' }],
16
+ rekey: {
17
+ seasonName: 'flexPLMSeasonName',
18
+ },
19
+ },
20
+ flex2vibe: {
21
+ transformOrder: [{ processor: 'REKEY', rekeyDelete: true, rekeyTransformersKey: 'rekey' }],
22
+ rekey: {
23
+ flexPLMSeasonName: 'seasonName',
24
+ },
25
+ },
26
+ },
27
+ LCSProduct: {
28
+ vibeOwningKeys: ['itemNumber'],
29
+ vibe2flex: {
30
+ transformOrder: [{ processor: 'REKEY', rekeyDelete: true, rekeyTransformersKey: 'rekey' }],
31
+ rekey: {
32
+ vibeIQIdentifier: 'itemNumber',
33
+ productName: 'name',
34
+ },
35
+ },
36
+ flex2vibe: {
37
+ transformOrder: [{ processor: 'REKEY', rekeyDelete: true, rekeyTransformersKey: 'rekey' }],
38
+ rekey: {
39
+ itemNumber: 'vibeIQIdentifier',
40
+ name: 'productName',
41
+ },
42
+ },
43
+ },
44
+ LCSSKU: {
45
+ vibeOwningKeys: ['itemNumber'],
46
+ vibe2flex: {
47
+ transformOrder: [{ processor: 'REKEY', rekeyDelete: true, rekeyTransformersKey: 'rekey' }],
48
+ rekey: {
49
+ vibeIQIdentifier: 'itemNumber',
50
+ skuName: 'optionName',
51
+ },
52
+ },
53
+ flex2vibe: {
54
+ transformOrder: [{ processor: 'REKEY', rekeyDelete: true, rekeyTransformersKey: 'rekey' }],
55
+ rekey: {
56
+ itemNumber: 'vibeIQIdentifier',
57
+ optionName: 'skuName',
58
+ },
59
+ },
60
+ },
61
+
62
+ };
@@ -19,18 +19,64 @@ export declare abstract class BaseEntityProcessor {
19
19
  inbound(event: EntityPayloadType): Promise<any>;
20
20
  handleIncomingUpsert(event: EntityPayloadType): Promise<any>;
21
21
  getInboundStatusMessage(statusObject: any): string;
22
+ /** Looks up an identity record from the identity service based on the passed in criteria.
23
+ * If no identity record is found, returns undefined. If multiple are found, throws an error.
24
+ *
25
+ * @param params.poolKey the key to use for the identity service pool. This will be the subtype uniqueness is defined on, typically the root type. Ex: 'item' or 'item:material'
26
+ * @param params.propertyName the name of the property to use for the criteria. Ex: 'itemNumber'
27
+ * @param params.propertyValue the value of the property to use for the criteria. Ex: '12345'
28
+ * @returns the identity entity, or undefined if no identity record is found
29
+ * @throws error if multiple identity entities are found, or if required parameters are missing
30
+ */
22
31
  getIdentityEntity(params: {
23
32
  poolKey: string;
24
33
  propertyName: string;
25
34
  propertyValue: string;
26
35
  }): Promise<any | undefined>;
36
+ /** Looks up an entity via the identity service. Uses {@link getIdentityEntity} to find the identity record,
37
+ * then resolves the entity reference to fetch and return the actual entity.
38
+ *
39
+ * @param params.poolKey the key to use for the identity service pool. This will be the subtype uniqueness is defined on, typically the root type. Ex: 'item' or 'item:material'
40
+ * @param params.propertyName the name of the property to use for the criteria. Ex: 'itemNumber'
41
+ * @param params.propertyValue the value of the property to use for the criteria. Ex: '12345'
42
+ * @returns the resolved entity, or undefined if no identity record is found
43
+ * @throws error if multiple identity entities are found, or if required parameters are missing
44
+ */
27
45
  getEntityUsingIdentityService(params: {
28
46
  poolKey: string;
29
47
  propertyName: string;
30
48
  propertyValue: string;
31
49
  }): Promise<any | undefined>;
50
+ /**This will query for the entity, and handle post-processing
51
+ * of any critieria that is defined at the sub-type level.
52
+ * Because sub-type criteria can't be used in the search done
53
+ * on the server. This is expected to be called by getIncomingEntity().
54
+ *
55
+ * @param entityType: the root type of the entity
56
+ * @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
57
+ * @param propertyCriteria: all the criteria to search for the entity
58
+ * @returns the entities that match the criteria
59
+ */
32
60
  queryEntityWithSubTypeCriteria(entityType: string, entityTypePath: string, propertyCriteria: any): Promise<any[]>;
61
+ /** This is to get the criteria for the entity that is being processed.
62
+ * This is to be overridden for item & project-item because of the need for
63
+ * setting the roles criteria.
64
+ *
65
+ * @param entityType: the root type of the entity
66
+ * @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
67
+ * @param propertyCriteria: all the criteria to search for the entity
68
+ * @returns the criteria for the entity
69
+ */
33
70
  getCriteriaForEntity(entityType: string, entityTypePath: string, propertyCriteria: any): Promise<any>;
71
+ /** This is to get the properties that are owned by the root type
72
+ * This needs to be overridded for multi-level types, such as item
73
+ * and project-item. And for those types, the propertyCriteria
74
+ * will be needed to determine the correct level.
75
+ *
76
+ * @param rootType: the full root type entity for the processed entity
77
+ * @param propertyCriteria: the criteria to determine the correct level (unused for single level types)
78
+ * @returns: string[] of the property keys
79
+ */
34
80
  getRootTypePropertyKeys(rootType: any, propertyCriteria?: any): string[];
35
81
  handleIncomingDelete(event: any): Promise<void>;
36
82
  getTransformedData(event: any): Promise<any>;
@@ -46,7 +92,26 @@ export declare abstract class BaseEntityProcessor {
46
92
  getOutboundEntityUpdates(event: any, flexResponse: any): Promise<any>;
47
93
  handleOutgoingDelete(entityType: any, event: any): Promise<void>;
48
94
  protected abstract getOutgoingUpsertPayload(entityType: any, event: any): Promise<EntityPayloadType>;
95
+ /** Create a new event-workflow-request to rerun sending the entity to FlexPLM
96
+ * The event must contain any information needed to ensure it is put in the correct queue for the entity
97
+ *
98
+ * @param triggerKey Ex: event.entityType + '|sendUpsertToFlexPLM'
99
+ * @param event
100
+ * @returns
101
+ */
49
102
  protected triggerNewEvent(triggerKey: string, event: any): Promise<any>;
103
+ /** Sends the current state of the entity to FlexPLM.
104
+ * So any changes made in Vibe between the event being generated and the event being processed are sent to FlexPLM.
105
+ *
106
+ * @param event must contain entityType, id; which are used to query for the entity
107
+ * @returns results of sending the entity to FlexPLM
108
+ */
50
109
  protected sendUpsertToFlexPLM(event: any): Promise<any>;
110
+ /** Generates the payload to send to FlexPLM, based on the current state of the entity.
111
+ * The current state of the entity are used as the newData and oldData; which is passed
112
+ * to getOutgoingUpsertPayload to generate the payload.
113
+ * @param event information about the item to send to FlexPLM
114
+ * @returns The payload to send to FlexPLM
115
+ */
51
116
  protected getEntityCurrentStateUpsertPayload(event: any): Promise<EntityPayloadType>;
52
117
  }
@@ -23,6 +23,7 @@ class BaseEntityProcessor {
23
23
  this.entities = new sdk_1.Entities();
24
24
  this.orgSlug = this.config?.orgSlug || 'unset-orgSlug';
25
25
  }
26
+ // inbound
26
27
  async inbound(event) {
27
28
  const eventType = event.eventType;
28
29
  console.log(`inbound entity: ${eventType}:${event.objectClass}`);
@@ -42,6 +43,7 @@ class BaseEntityProcessor {
42
43
  async handleIncomingUpsert(event) {
43
44
  const inboundData = await this.getTransformedData(event);
44
45
  const incomingEntityResponse = await this.getIncomingEntity(event, inboundData);
46
+ // This case means there was an early return in the getIncomingEntity method
45
47
  if (incomingEntityResponse.earlyReturn) {
46
48
  const statusMsg = this.getInboundStatusMessage({
47
49
  status: event_short_message_status_1.EventShortMessageStatus.FAILURE,
@@ -136,6 +138,15 @@ class BaseEntityProcessor {
136
138
  + ', federatedId: ' + statusObject.federatedId
137
139
  + ', orgSlug: ' + this.orgSlug;
138
140
  }
141
+ /** Looks up an identity record from the identity service based on the passed in criteria.
142
+ * If no identity record is found, returns undefined. If multiple are found, throws an error.
143
+ *
144
+ * @param params.poolKey the key to use for the identity service pool. This will be the subtype uniqueness is defined on, typically the root type. Ex: 'item' or 'item:material'
145
+ * @param params.propertyName the name of the property to use for the criteria. Ex: 'itemNumber'
146
+ * @param params.propertyValue the value of the property to use for the criteria. Ex: '12345'
147
+ * @returns the identity entity, or undefined if no identity record is found
148
+ * @throws error if multiple identity entities are found, or if required parameters are missing
149
+ */
139
150
  async getIdentityEntity(params) {
140
151
  const { poolKey, propertyName, propertyValue } = params;
141
152
  if (!poolKey || !propertyName || !propertyValue) {
@@ -157,6 +168,15 @@ class BaseEntityProcessor {
157
168
  }
158
169
  return Array.isArray(identityEntities) ? identityEntities[0] : identityEntities;
159
170
  }
171
+ /** Looks up an entity via the identity service. Uses {@link getIdentityEntity} to find the identity record,
172
+ * then resolves the entity reference to fetch and return the actual entity.
173
+ *
174
+ * @param params.poolKey the key to use for the identity service pool. This will be the subtype uniqueness is defined on, typically the root type. Ex: 'item' or 'item:material'
175
+ * @param params.propertyName the name of the property to use for the criteria. Ex: 'itemNumber'
176
+ * @param params.propertyValue the value of the property to use for the criteria. Ex: '12345'
177
+ * @returns the resolved entity, or undefined if no identity record is found
178
+ * @throws error if multiple identity entities are found, or if required parameters are missing
179
+ */
160
180
  async getEntityUsingIdentityService(params) {
161
181
  const identityEntity = await this.getIdentityEntity(params);
162
182
  if (!identityEntity) {
@@ -170,7 +190,18 @@ class BaseEntityProcessor {
170
190
  });
171
191
  return entity;
172
192
  }
193
+ /**This will query for the entity, and handle post-processing
194
+ * of any critieria that is defined at the sub-type level.
195
+ * Because sub-type criteria can't be used in the search done
196
+ * on the server. This is expected to be called by getIncomingEntity().
197
+ *
198
+ * @param entityType: the root type of the entity
199
+ * @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
200
+ * @param propertyCriteria: all the criteria to search for the entity
201
+ * @returns the entities that match the criteria
202
+ */
173
203
  async queryEntityWithSubTypeCriteria(entityType, entityTypePath, propertyCriteria) {
204
+ //allCriteria; identifierKeys; entityType; entityTypePath
174
205
  if (!entityType || !entityTypePath) {
175
206
  throw new Error('type and entityTypePath must be defined');
176
207
  }
@@ -181,6 +212,15 @@ class BaseEntityProcessor {
181
212
  const returnedEntities = await this.dc.getAllObjectReferences(entityType, rootTypeCriteria, subTypeCriteria);
182
213
  return returnedEntities;
183
214
  }
215
+ /** This is to get the criteria for the entity that is being processed.
216
+ * This is to be overridden for item & project-item because of the need for
217
+ * setting the roles criteria.
218
+ *
219
+ * @param entityType: the root type of the entity
220
+ * @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
221
+ * @param propertyCriteria: all the criteria to search for the entity
222
+ * @returns the criteria for the entity
223
+ */
184
224
  async getCriteriaForEntity(entityType, entityTypePath, propertyCriteria) {
185
225
  if (!entityType || !entityTypePath) {
186
226
  throw new Error('type and entityTypePath must be defined');
@@ -205,6 +245,15 @@ class BaseEntityProcessor {
205
245
  }
206
246
  return { rootTypeCriteria, subTypeCriteria };
207
247
  }
248
+ /** This is to get the properties that are owned by the root type
249
+ * This needs to be overridded for multi-level types, such as item
250
+ * and project-item. And for those types, the propertyCriteria
251
+ * will be needed to determine the correct level.
252
+ *
253
+ * @param rootType: the full root type entity for the processed entity
254
+ * @param propertyCriteria: the criteria to determine the correct level (unused for single level types)
255
+ * @returns: string[] of the property keys
256
+ */
208
257
  getRootTypePropertyKeys(rootType, propertyCriteria = null) {
209
258
  const props = rootType['typeProperties'];
210
259
  const rootTypePropertyKeys = props.map(prop => prop.slug);
@@ -237,6 +286,8 @@ class BaseEntityProcessor {
237
286
  async getVibeOwningKeys(entity) {
238
287
  let vibeOwningKeys = [];
239
288
  if (this.transformMapFile && entity) {
289
+ //Technically the transform is flex->vibe. But the vibe entity being updated was passed in,
290
+ // so we use VIBE2FLEX_DIRECTION to get the mapKey
240
291
  const mapKey = await type_conversion_utils_1.TypeConversionUtils.getMapKey(this.transformMapFile, this.mapFileUtil, entity, type_conversion_utils_1.TypeConversionUtils.VIBE2FLEX_DIRECTION);
241
292
  const mapSection = await map_utils_1.MapUtil.getFullMapSection(this.transformMapFile, this.mapFileUtil, mapKey);
242
293
  vibeOwningKeys = mapSection?.vibeOwningKeys || [];
@@ -271,6 +322,7 @@ class BaseEntityProcessor {
271
322
  console.log('updateEntity: ' + JSON.stringify(options));
272
323
  return await new sdk_1.Entities().update(options);
273
324
  }
325
+ // outbound
274
326
  async outbound(event) {
275
327
  const entityType = event.entityType;
276
328
  const eventType = event.eventType;
@@ -347,6 +399,13 @@ class BaseEntityProcessor {
347
399
  async handleOutgoingDelete(entityType, event) {
348
400
  console.warn('delete is not configured', entityType, event.oldData);
349
401
  }
402
+ /** Create a new event-workflow-request to rerun sending the entity to FlexPLM
403
+ * The event must contain any information needed to ensure it is put in the correct queue for the entity
404
+ *
405
+ * @param triggerKey Ex: event.entityType + '|sendUpsertToFlexPLM'
406
+ * @param event
407
+ * @returns
408
+ */
350
409
  async triggerNewEvent(triggerKey, event) {
351
410
  const newEvent = {
352
411
  entityName: 'event-workflow-request',
@@ -358,6 +417,12 @@ class BaseEntityProcessor {
358
417
  const response = await this.entities.create(newEvent);
359
418
  return response;
360
419
  }
420
+ /** Sends the current state of the entity to FlexPLM.
421
+ * So any changes made in Vibe between the event being generated and the event being processed are sent to FlexPLM.
422
+ *
423
+ * @param event must contain entityType, id; which are used to query for the entity
424
+ * @returns results of sending the entity to FlexPLM
425
+ */
361
426
  async sendUpsertToFlexPLM(event) {
362
427
  const payload = await this.getEntityCurrentStateUpsertPayload(event);
363
428
  if (!payload) {
@@ -398,6 +463,12 @@ class BaseEntityProcessor {
398
463
  throw e;
399
464
  }
400
465
  }
466
+ /** Generates the payload to send to FlexPLM, based on the current state of the entity.
467
+ * The current state of the entity are used as the newData and oldData; which is passed
468
+ * to getOutgoingUpsertPayload to generate the payload.
469
+ * @param event information about the item to send to FlexPLM
470
+ * @returns The payload to send to FlexPLM
471
+ */
401
472
  async getEntityCurrentStateUpsertPayload(event) {
402
473
  const id = event.id;
403
474
  if (!id) {
@@ -269,6 +269,7 @@ describe('BaseEntityProcessor', () => {
269
269
  const rootCriteriaResults = Object.assign({}, rootCriteria);
270
270
  const subCriteriaResults = Object.assign({}, subCriteria);
271
271
  const mockGetByRootTypeProperties = jest.spyOn(btep, 'getRootTypePropertyKeys').mockReturnValue(['rootText']);
272
+ // const mockDCgetAllObjectReferences = jest.spyOn(dc, 'getAllObjectReferences').mockReturnValue(Promise.resolve([]));
272
273
  const { rootTypeCriteria, subTypeCriteria } = await btep.getCriteriaForEntity(entityType, entityTypePath, propertyCriteria);
273
274
  expect(mockTypeUtilGetByRootAndPath).toBeCalledTimes(1);
274
275
  expect(mockTypeUtilGetByRootAndPath).toBeCalledWith({ root: entityType });
package/lib/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export * from './util/map-utils';
16
16
  export * from './interfaces/interfaces';
17
17
  export * from './interfaces/item-family-changes';
18
18
  export * from './interfaces/publish-change-data';
19
+ export * from './interfaces/mapping-file';
19
20
  export * from './publish/base-process-publish-assortment';
20
21
  export * from './publish/base-process-publish-assortment-callback';
21
22
  export * from './entity-processor/base-entity-processor';
package/lib/index.js CHANGED
@@ -32,6 +32,7 @@ __exportStar(require("./util/map-utils"), exports);
32
32
  __exportStar(require("./interfaces/interfaces"), exports);
33
33
  __exportStar(require("./interfaces/item-family-changes"), exports);
34
34
  __exportStar(require("./interfaces/publish-change-data"), exports);
35
+ __exportStar(require("./interfaces/mapping-file"), exports);
35
36
  __exportStar(require("./publish/base-process-publish-assortment"), exports);
36
37
  __exportStar(require("./publish/base-process-publish-assortment-callback"), exports);
37
38
  __exportStar(require("./entity-processor/base-entity-processor"), exports);