@contrail/flexplm 1.3.1-alpha.763fca8 → 1.3.1-alpha.8bc920d
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/.github/pull_request_template.md +31 -0
- package/.github/workflows/flexplm-lib.yml +27 -0
- package/.github/workflows/publish-to-npm.yml +121 -0
- package/CHANGELOG.md +32 -0
- package/lib/entity-processor/base-entity-processor.d.ts +0 -47
- package/lib/entity-processor/base-entity-processor.js +0 -53
- package/lib/entity-processor/base-entity-processor.spec.js +0 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/publish/base-process-publish-assortment.d.ts +0 -25
- package/lib/publish/base-process-publish-assortment.js +6 -60
- package/lib/publish/base-process-publish-assortment.spec.js +4 -22
- package/lib/publish/mockData.js +0 -5
- package/lib/transform/identifier-conversion-spec-mockData.js +6 -34
- package/lib/transform/identifier-conversion.d.ts +0 -36
- package/lib/transform/identifier-conversion.js +0 -36
- package/lib/transform/identifier-conversion.spec.js +0 -4
- package/lib/util/config-defaults.js +0 -3
- package/lib/util/config-defaults.spec.js +0 -9
- package/lib/util/data-converter-spec-mockData.js +3 -17
- package/lib/util/data-converter.d.ts +0 -97
- package/lib/util/data-converter.js +4 -127
- package/lib/util/data-converter.spec.js +0 -2
- package/lib/util/error-response-object.d.ts +0 -5
- package/lib/util/error-response-object.js +0 -7
- package/lib/util/event-short-message-status.js +0 -1
- package/lib/util/federation.js +0 -8
- package/lib/util/flexplm-connect.d.ts +0 -7
- package/lib/util/flexplm-connect.js +0 -14
- package/lib/util/logger-config.js +0 -1
- package/lib/util/map-util-spec-mockData.js +3 -17
- package/lib/util/map-utils.d.ts +0 -27
- package/lib/util/map-utils.js +0 -27
- package/lib/util/thumbnail-util.d.ts +0 -21
- package/lib/util/thumbnail-util.js +1 -28
- package/lib/util/thumbnail-util.spec.js +0 -6
- package/lib/util/type-conversion-utils-spec-mockData.js +3 -3
- package/lib/util/type-conversion-utils.d.ts +0 -140
- package/lib/util/type-conversion-utils.js +0 -143
- package/lib/util/type-defaults.d.ts +0 -58
- package/lib/util/type-defaults.js +0 -58
- package/lib/util/type-defaults.spec.js +5 -5
- package/lib/util/type-utils.d.ts +0 -21
- package/lib/util/type-utils.js +0 -23
- package/lib/util/type-utils.spec.js +0 -2
- package/package.json +6 -21
- package/publish.bat +5 -0
- package/publish.sh +5 -0
- package/src/entity-processor/base-entity-processor.spec.ts +460 -0
- package/src/entity-processor/base-entity-processor.ts +515 -0
- package/src/flexplm-request.ts +28 -0
- package/src/flexplm-utils.spec.ts +27 -0
- package/src/flexplm-utils.ts +29 -0
- package/src/index.ts +22 -0
- package/src/interfaces/interfaces.ts +122 -0
- package/src/interfaces/item-family-changes.ts +67 -0
- package/src/interfaces/publish-change-data.ts +43 -0
- package/src/publish/base-process-publish-assortment-callback.ts +50 -0
- package/src/publish/base-process-publish-assortment.spec.ts +1992 -0
- package/src/publish/base-process-publish-assortment.ts +1134 -0
- package/src/publish/mockData.ts +4561 -0
- package/src/transform/identifier-conversion-spec-mockData.ts +496 -0
- package/src/transform/identifier-conversion.spec.ts +354 -0
- package/src/transform/identifier-conversion.ts +282 -0
- package/src/util/config-defaults.spec.ts +350 -0
- package/src/util/config-defaults.ts +93 -0
- package/src/util/data-converter-spec-mockData.ts +231 -0
- package/src/util/data-converter.spec.ts +1041 -0
- package/src/util/data-converter.ts +764 -0
- package/src/util/error-response-object.spec.ts +116 -0
- package/src/util/error-response-object.ts +50 -0
- package/src/util/event-short-message-status.ts +22 -0
- package/src/util/federation.ts +172 -0
- package/src/util/flexplm-connect.spec.ts +132 -0
- package/src/util/flexplm-connect.ts +208 -0
- package/src/util/logger-config.ts +20 -0
- package/src/util/map-util-spec-mockData.ts +231 -0
- package/src/util/map-utils.spec.ts +103 -0
- package/src/util/map-utils.ts +41 -0
- package/src/util/mockData.ts +101 -0
- package/src/util/thumbnail-util.spec.ts +508 -0
- package/src/util/thumbnail-util.ts +272 -0
- package/src/util/type-conversion-utils-spec-mockData.ts +271 -0
- package/src/util/type-conversion-utils.spec.ts +968 -0
- package/src/util/type-conversion-utils.ts +460 -0
- package/src/util/type-defaults.spec.ts +669 -0
- package/src/util/type-defaults.ts +281 -0
- package/src/util/type-utils.spec.ts +227 -0
- package/src/util/type-utils.ts +144 -0
- package/tsconfig.json +24 -0
- package/tslint.json +57 -0
- package/lib/cli/commands/compile.d.ts +0 -1
- package/lib/cli/commands/compile.js +0 -71
- package/lib/cli/commands/compile.spec.d.ts +0 -1
- package/lib/cli/commands/compile.spec.js +0 -80
- package/lib/cli/commands/create.d.ts +0 -1
- package/lib/cli/commands/create.js +0 -75
- package/lib/cli/commands/create.spec.d.ts +0 -1
- package/lib/cli/commands/create.spec.js +0 -78
- package/lib/cli/commands/upload.d.ts +0 -10
- package/lib/cli/commands/upload.js +0 -219
- package/lib/cli/commands/upload.spec.d.ts +0 -1
- package/lib/cli/commands/upload.spec.js +0 -88
- package/lib/cli/index.d.ts +0 -2
- package/lib/cli/index.js +0 -64
- package/lib/cli/index.spec.d.ts +0 -1
- package/lib/cli/index.spec.js +0 -79
- package/lib/cli/template/mapping-template.ts.template +0 -18
- package/lib/interfaces/mapping-file.d.ts +0 -429
- package/lib/interfaces/mapping-file.js +0 -2
- package/scripts/copy-template.js +0 -10
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## What
|
|
2
|
+
- [ ] Bugfix
|
|
3
|
+
- [ ] Feature
|
|
4
|
+
- [ ] Enhancement
|
|
5
|
+
|
|
6
|
+
Description:
|
|
7
|
+
<!--
|
|
8
|
+
Describe the functional changes of the PR.
|
|
9
|
+
|
|
10
|
+
If the mechanism of your change are complex, describe them in detail as you
|
|
11
|
+
would if you were explaining them to a team mate.
|
|
12
|
+
|
|
13
|
+
If the PR is simple, there is no need to repeat yourself. A small description
|
|
14
|
+
is sufficient.
|
|
15
|
+
-->
|
|
16
|
+
|
|
17
|
+
## Why
|
|
18
|
+
<!--
|
|
19
|
+
why is this change needed? Same rules as with #What
|
|
20
|
+
-->
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Testing added
|
|
24
|
+
<!--
|
|
25
|
+
Describe the testing you added to this PR
|
|
26
|
+
-->
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Link to Jira ticket(s)
|
|
30
|
+
https://vibe-team.atlassian.net/browse/VIBE-TICKET_NUMBER_HERE
|
|
31
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: flexplm-lib-tests
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
workflow_dispatch: # allow running in github actions manually
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-24.04
|
|
8
|
+
strategy:
|
|
9
|
+
matrix:
|
|
10
|
+
node-version: [22.14.0, 24]
|
|
11
|
+
steps:
|
|
12
|
+
- name: Node.js
|
|
13
|
+
uses: actions/setup-node@v3
|
|
14
|
+
with:
|
|
15
|
+
node-version: ${{ matrix.node-version }}
|
|
16
|
+
|
|
17
|
+
- uses: actions/checkout@v3
|
|
18
|
+
|
|
19
|
+
- name: NPM Install
|
|
20
|
+
env:
|
|
21
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
22
|
+
run: npm ci
|
|
23
|
+
|
|
24
|
+
- name: Unit Tests -
|
|
25
|
+
env:
|
|
26
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
27
|
+
run: npm test
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
name: Publish to NPM
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '.github/**'
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [master]
|
|
10
|
+
paths-ignore:
|
|
11
|
+
- '.github/**'
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
check-version:
|
|
15
|
+
name: Verify version is available on npm
|
|
16
|
+
if: github.event_name == 'pull_request'
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Check version not already published
|
|
22
|
+
run: |
|
|
23
|
+
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
24
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
25
|
+
echo "Checking if ${PACKAGE_NAME}@${VERSION} exists on npm..."
|
|
26
|
+
if npm view "${PACKAGE_NAME}@${VERSION}" version 2>/dev/null; then
|
|
27
|
+
echo "::error::Version ${VERSION} is already published on npm. Bump the version in package.json before merging."
|
|
28
|
+
exit 1
|
|
29
|
+
else
|
|
30
|
+
echo "Version ${VERSION} is available."
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
check-dependencies:
|
|
34
|
+
name: Verify no private dependencies
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
|
|
39
|
+
- name: Verify no private dependencies
|
|
40
|
+
run: |
|
|
41
|
+
node -e "
|
|
42
|
+
const deps = require('./package.json').dependencies || {};
|
|
43
|
+
const { execSync } = require('child_process');
|
|
44
|
+
let failed = false;
|
|
45
|
+
for (const pkg of Object.keys(deps)) {
|
|
46
|
+
try {
|
|
47
|
+
execSync('npm view ' + pkg, { stdio: 'pipe' });
|
|
48
|
+
} catch {
|
|
49
|
+
console.error('::error::Dependency ' + pkg + ' is not publicly accessible on npm');
|
|
50
|
+
failed = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (failed) process.exit(1);
|
|
54
|
+
console.log('All ' + Object.keys(deps).length + ' dependencies are public.');
|
|
55
|
+
"
|
|
56
|
+
|
|
57
|
+
publish-alpha:
|
|
58
|
+
name: Publish alpha
|
|
59
|
+
needs: check-dependencies
|
|
60
|
+
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
permissions:
|
|
63
|
+
id-token: write
|
|
64
|
+
contents: read
|
|
65
|
+
outputs:
|
|
66
|
+
version: ${{ steps.publish.outputs.version }}
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@v4
|
|
69
|
+
|
|
70
|
+
- uses: actions/setup-node@v4
|
|
71
|
+
with:
|
|
72
|
+
node-version: '24'
|
|
73
|
+
registry-url: 'https://registry.npmjs.org'
|
|
74
|
+
|
|
75
|
+
- name: Install and build
|
|
76
|
+
run: npm ci && npm run build
|
|
77
|
+
|
|
78
|
+
- name: Publish alpha
|
|
79
|
+
id: publish
|
|
80
|
+
run: |
|
|
81
|
+
SHORT_SHA=$(echo ${{ github.event.pull_request.head.sha }} | cut -c1-7)
|
|
82
|
+
VERSION=$(node -p "require('./package.json').version")-alpha.${SHORT_SHA}
|
|
83
|
+
npm version $VERSION --no-git-tag-version
|
|
84
|
+
OUTPUT=$(npm publish --tag alpha 2>&1) && {
|
|
85
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
86
|
+
} || {
|
|
87
|
+
if echo "$OUTPUT" | grep -q "You cannot publish over the previously published versions"; then
|
|
88
|
+
echo "::warning::Alpha ${VERSION} already published, skipping."
|
|
89
|
+
else
|
|
90
|
+
echo "::error::Failed to publish alpha ${VERSION}"
|
|
91
|
+
echo "$OUTPUT"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
publish-release:
|
|
97
|
+
name: Publish release
|
|
98
|
+
needs: check-dependencies
|
|
99
|
+
if: github.event_name == 'push'
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
permissions:
|
|
102
|
+
id-token: write
|
|
103
|
+
contents: read
|
|
104
|
+
outputs:
|
|
105
|
+
version: ${{ steps.publish.outputs.version }}
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@v4
|
|
108
|
+
|
|
109
|
+
- uses: actions/setup-node@v4
|
|
110
|
+
with:
|
|
111
|
+
node-version: '24'
|
|
112
|
+
registry-url: 'https://registry.npmjs.org'
|
|
113
|
+
|
|
114
|
+
- name: Install and build
|
|
115
|
+
run: npm ci && npm run build
|
|
116
|
+
|
|
117
|
+
- name: Publish release
|
|
118
|
+
id: publish
|
|
119
|
+
run: |
|
|
120
|
+
npm publish
|
|
121
|
+
echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@contrail/flexplm` are documented here.
|
|
4
|
+
|
|
5
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
|
+
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.3.0] - 2026-04-15
|
|
11
|
+
### Added
|
|
12
|
+
- Added inbound thumbnail/primary content syncing from FlexPLM to VibeIQ via `ThumbnailUtil.syncThumbnailToVibeIQ`.
|
|
13
|
+
- Added `syncInboundImages` and `syncOutboundImages` methods to `TypeConversionUtils` for controlling image sync per map file configuration.
|
|
14
|
+
- Added `PRIMARY_CONTENT_UPDATED` status to `EventShortMessageStatus` for when only primary content changes are detected.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- `BaseEntityProcessor` update flow now distinguishes between primary-content-only changes and no changes, returning the updated entity when only the thumbnail was synced.
|
|
18
|
+
- Improved `FlexPLMConnect.getRequest` function and added unit tests.
|
|
19
|
+
|
|
20
|
+
## [1.2.1] - 2026-04-08
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- Added EventShortMessageStatus status values for adding items to projects functionality.
|
|
24
|
+
- Added `TypeConversionUtils.isOutboundCreatableFromEntity` method to determine if VibeIQ entities are creatable in FlexPLM (defaults to true).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Added optional `context` parameter to `TypeConversionUtils.isInboundCreatableFromObject` method to allow passing context data to map file `isInboundCreatable` functions.
|
|
28
|
+
|
|
29
|
+
## [1.1.66] - (initial changelog entry)
|
|
30
|
+
|
|
31
|
+
- Initial changelog. Prior releases did not include a changelog.
|
|
32
|
+
See git history for changes predating this entry.
|
|
@@ -19,36 +19,8 @@ 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
|
-
/**This will query for the entity, and handle post-processing
|
|
23
|
-
* of any critieria that is defined at the sub-type level.
|
|
24
|
-
* Because sub-type criteria can't be used in the search done
|
|
25
|
-
* on the server. This is expected to be called by getIncomingEntity().
|
|
26
|
-
*
|
|
27
|
-
* @param entityType: the root type of the entity
|
|
28
|
-
* @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
|
|
29
|
-
* @param propertyCriteria: all the criteria to search for the entity
|
|
30
|
-
* @returns the entities that match the criteria
|
|
31
|
-
*/
|
|
32
22
|
queryEntityWithSubTypeCriteria(entityType: string, entityTypePath: string, propertyCriteria: any): Promise<any[]>;
|
|
33
|
-
/** This is to get the criteria for the entity that is being processed.
|
|
34
|
-
* This is to be overridden for item & project-item because of the need for
|
|
35
|
-
* setting the roles criteria.
|
|
36
|
-
*
|
|
37
|
-
* @param entityType: the root type of the entity
|
|
38
|
-
* @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
|
|
39
|
-
* @param propertyCriteria: all the criteria to search for the entity
|
|
40
|
-
* @returns the criteria for the entity
|
|
41
|
-
*/
|
|
42
23
|
getCriteriaForEntity(entityType: string, entityTypePath: string, propertyCriteria: any): Promise<any>;
|
|
43
|
-
/** This is to get the properties that are owned by the root type
|
|
44
|
-
* This needs to be overridded for multi-level types, such as item
|
|
45
|
-
* and project-item. And for those types, the propertyCriteria
|
|
46
|
-
* will be needed to determine the correct level.
|
|
47
|
-
*
|
|
48
|
-
* @param rootType: the full root type entity for the processed entity
|
|
49
|
-
* @param propertyCriteria: the criteria to determine the correct level (unused for single level types)
|
|
50
|
-
* @returns: string[] of the property keys
|
|
51
|
-
*/
|
|
52
24
|
getRootTypePropertyKeys(rootType: any, propertyCriteria?: any): string[];
|
|
53
25
|
handleIncomingDelete(event: any): Promise<void>;
|
|
54
26
|
getTransformedData(event: any): Promise<any>;
|
|
@@ -64,26 +36,7 @@ export declare abstract class BaseEntityProcessor {
|
|
|
64
36
|
getOutboundEntityUpdates(event: any, flexResponse: any): Promise<any>;
|
|
65
37
|
handleOutgoingDelete(entityType: any, event: any): Promise<void>;
|
|
66
38
|
protected abstract getOutgoingUpsertPayload(entityType: any, event: any): Promise<EntityPayloadType>;
|
|
67
|
-
/** Create a new event-workflow-request to rerun sending the entity to FlexPLM
|
|
68
|
-
* The event must contain any information needed to ensure it is put in the correct queue for the entity
|
|
69
|
-
*
|
|
70
|
-
* @param triggerKey Ex: event.entityType + '|sendUpsertToFlexPLM'
|
|
71
|
-
* @param event
|
|
72
|
-
* @returns
|
|
73
|
-
*/
|
|
74
39
|
protected triggerNewEvent(triggerKey: string, event: any): Promise<any>;
|
|
75
|
-
/** Sends the current state of the entity to FlexPLM.
|
|
76
|
-
* So any changes made in Vibe between the event being generated and the event being processed are sent to FlexPLM.
|
|
77
|
-
*
|
|
78
|
-
* @param event must contain entityType, id; which are used to query for the entity
|
|
79
|
-
* @returns results of sending the entity to FlexPLM
|
|
80
|
-
*/
|
|
81
40
|
protected sendUpsertToFlexPLM(event: any): Promise<any>;
|
|
82
|
-
/** Generates the payload to send to FlexPLM, based on the current state of the entity.
|
|
83
|
-
* The current state of the entity are used as the newData and oldData; which is passed
|
|
84
|
-
* to getOutgoingUpsertPayload to generate the payload.
|
|
85
|
-
* @param event information about the item to send to FlexPLM
|
|
86
|
-
* @returns The payload to send to FlexPLM
|
|
87
|
-
*/
|
|
88
41
|
protected getEntityCurrentStateUpsertPayload(event: any): Promise<EntityPayloadType>;
|
|
89
42
|
}
|
|
@@ -23,7 +23,6 @@ class BaseEntityProcessor {
|
|
|
23
23
|
this.entities = new sdk_1.Entities();
|
|
24
24
|
this.orgSlug = this.config?.orgSlug || 'unset-orgSlug';
|
|
25
25
|
}
|
|
26
|
-
// inbound
|
|
27
26
|
async inbound(event) {
|
|
28
27
|
const eventType = event.eventType;
|
|
29
28
|
console.log(`inbound entity: ${eventType}:${event.objectClass}`);
|
|
@@ -43,7 +42,6 @@ class BaseEntityProcessor {
|
|
|
43
42
|
async handleIncomingUpsert(event) {
|
|
44
43
|
const inboundData = await this.getTransformedData(event);
|
|
45
44
|
const incomingEntityResponse = await this.getIncomingEntity(event, inboundData);
|
|
46
|
-
// This case means there was an early return in the getIncomingEntity method
|
|
47
45
|
if (incomingEntityResponse.earlyReturn) {
|
|
48
46
|
const statusMsg = this.getInboundStatusMessage({
|
|
49
47
|
status: event_short_message_status_1.EventShortMessageStatus.FAILURE,
|
|
@@ -138,18 +136,7 @@ class BaseEntityProcessor {
|
|
|
138
136
|
+ ', federatedId: ' + statusObject.federatedId
|
|
139
137
|
+ ', orgSlug: ' + this.orgSlug;
|
|
140
138
|
}
|
|
141
|
-
/**This will query for the entity, and handle post-processing
|
|
142
|
-
* of any critieria that is defined at the sub-type level.
|
|
143
|
-
* Because sub-type criteria can't be used in the search done
|
|
144
|
-
* on the server. This is expected to be called by getIncomingEntity().
|
|
145
|
-
*
|
|
146
|
-
* @param entityType: the root type of the entity
|
|
147
|
-
* @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
|
|
148
|
-
* @param propertyCriteria: all the criteria to search for the entity
|
|
149
|
-
* @returns the entities that match the criteria
|
|
150
|
-
*/
|
|
151
139
|
async queryEntityWithSubTypeCriteria(entityType, entityTypePath, propertyCriteria) {
|
|
152
|
-
//allCriteria; identifierKeys; entityType; entityTypePath
|
|
153
140
|
if (!entityType || !entityTypePath) {
|
|
154
141
|
throw new Error('type and entityTypePath must be defined');
|
|
155
142
|
}
|
|
@@ -160,15 +147,6 @@ class BaseEntityProcessor {
|
|
|
160
147
|
const returnedEntities = await this.dc.getAllObjectReferences(entityType, rootTypeCriteria, subTypeCriteria);
|
|
161
148
|
return returnedEntities;
|
|
162
149
|
}
|
|
163
|
-
/** This is to get the criteria for the entity that is being processed.
|
|
164
|
-
* This is to be overridden for item & project-item because of the need for
|
|
165
|
-
* setting the roles criteria.
|
|
166
|
-
*
|
|
167
|
-
* @param entityType: the root type of the entity
|
|
168
|
-
* @param entityTypePath: the full type path of the entity. Ex: custom-entity:sample
|
|
169
|
-
* @param propertyCriteria: all the criteria to search for the entity
|
|
170
|
-
* @returns the criteria for the entity
|
|
171
|
-
*/
|
|
172
150
|
async getCriteriaForEntity(entityType, entityTypePath, propertyCriteria) {
|
|
173
151
|
if (!entityType || !entityTypePath) {
|
|
174
152
|
throw new Error('type and entityTypePath must be defined');
|
|
@@ -193,15 +171,6 @@ class BaseEntityProcessor {
|
|
|
193
171
|
}
|
|
194
172
|
return { rootTypeCriteria, subTypeCriteria };
|
|
195
173
|
}
|
|
196
|
-
/** This is to get the properties that are owned by the root type
|
|
197
|
-
* This needs to be overridded for multi-level types, such as item
|
|
198
|
-
* and project-item. And for those types, the propertyCriteria
|
|
199
|
-
* will be needed to determine the correct level.
|
|
200
|
-
*
|
|
201
|
-
* @param rootType: the full root type entity for the processed entity
|
|
202
|
-
* @param propertyCriteria: the criteria to determine the correct level (unused for single level types)
|
|
203
|
-
* @returns: string[] of the property keys
|
|
204
|
-
*/
|
|
205
174
|
getRootTypePropertyKeys(rootType, propertyCriteria = null) {
|
|
206
175
|
const props = rootType['typeProperties'];
|
|
207
176
|
const rootTypePropertyKeys = props.map(prop => prop.slug);
|
|
@@ -234,8 +203,6 @@ class BaseEntityProcessor {
|
|
|
234
203
|
async getVibeOwningKeys(entity) {
|
|
235
204
|
let vibeOwningKeys = [];
|
|
236
205
|
if (this.transformMapFile && entity) {
|
|
237
|
-
//Technically the transform is flex->vibe. But the vibe entity being updated was passed in,
|
|
238
|
-
// so we use VIBE2FLEX_DIRECTION to get the mapKey
|
|
239
206
|
const mapKey = await type_conversion_utils_1.TypeConversionUtils.getMapKey(this.transformMapFile, this.mapFileUtil, entity, type_conversion_utils_1.TypeConversionUtils.VIBE2FLEX_DIRECTION);
|
|
240
207
|
const mapSection = await map_utils_1.MapUtil.getFullMapSection(this.transformMapFile, this.mapFileUtil, mapKey);
|
|
241
208
|
vibeOwningKeys = mapSection?.vibeOwningKeys || [];
|
|
@@ -270,7 +237,6 @@ class BaseEntityProcessor {
|
|
|
270
237
|
console.log('updateEntity: ' + JSON.stringify(options));
|
|
271
238
|
return await new sdk_1.Entities().update(options);
|
|
272
239
|
}
|
|
273
|
-
// outbound
|
|
274
240
|
async outbound(event) {
|
|
275
241
|
const entityType = event.entityType;
|
|
276
242
|
const eventType = event.eventType;
|
|
@@ -347,13 +313,6 @@ class BaseEntityProcessor {
|
|
|
347
313
|
async handleOutgoingDelete(entityType, event) {
|
|
348
314
|
console.warn('delete is not configured', entityType, event.oldData);
|
|
349
315
|
}
|
|
350
|
-
/** Create a new event-workflow-request to rerun sending the entity to FlexPLM
|
|
351
|
-
* The event must contain any information needed to ensure it is put in the correct queue for the entity
|
|
352
|
-
*
|
|
353
|
-
* @param triggerKey Ex: event.entityType + '|sendUpsertToFlexPLM'
|
|
354
|
-
* @param event
|
|
355
|
-
* @returns
|
|
356
|
-
*/
|
|
357
316
|
async triggerNewEvent(triggerKey, event) {
|
|
358
317
|
const newEvent = {
|
|
359
318
|
entityName: 'event-workflow-request',
|
|
@@ -365,12 +324,6 @@ class BaseEntityProcessor {
|
|
|
365
324
|
const response = await this.entities.create(newEvent);
|
|
366
325
|
return response;
|
|
367
326
|
}
|
|
368
|
-
/** Sends the current state of the entity to FlexPLM.
|
|
369
|
-
* So any changes made in Vibe between the event being generated and the event being processed are sent to FlexPLM.
|
|
370
|
-
*
|
|
371
|
-
* @param event must contain entityType, id; which are used to query for the entity
|
|
372
|
-
* @returns results of sending the entity to FlexPLM
|
|
373
|
-
*/
|
|
374
327
|
async sendUpsertToFlexPLM(event) {
|
|
375
328
|
const payload = await this.getEntityCurrentStateUpsertPayload(event);
|
|
376
329
|
if (!payload) {
|
|
@@ -411,12 +364,6 @@ class BaseEntityProcessor {
|
|
|
411
364
|
throw e;
|
|
412
365
|
}
|
|
413
366
|
}
|
|
414
|
-
/** Generates the payload to send to FlexPLM, based on the current state of the entity.
|
|
415
|
-
* The current state of the entity are used as the newData and oldData; which is passed
|
|
416
|
-
* to getOutgoingUpsertPayload to generate the payload.
|
|
417
|
-
* @param event information about the item to send to FlexPLM
|
|
418
|
-
* @returns The payload to send to FlexPLM
|
|
419
|
-
*/
|
|
420
367
|
async getEntityCurrentStateUpsertPayload(event) {
|
|
421
368
|
const id = event.id;
|
|
422
369
|
if (!id) {
|
|
@@ -269,7 +269,6 @@ 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([]));
|
|
273
272
|
const { rootTypeCriteria, subTypeCriteria } = await btep.getCriteriaForEntity(entityType, entityTypePath, propertyCriteria);
|
|
274
273
|
expect(mockTypeUtilGetByRootAndPath).toBeCalledTimes(1);
|
|
275
274
|
expect(mockTypeUtilGetByRootAndPath).toBeCalledWith({ root: entityType });
|
package/lib/index.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ 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';
|
|
20
19
|
export * from './publish/base-process-publish-assortment';
|
|
21
20
|
export * from './publish/base-process-publish-assortment-callback';
|
|
22
21
|
export * from './entity-processor/base-entity-processor';
|
package/lib/index.js
CHANGED
|
@@ -32,7 +32,6 @@ __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);
|
|
36
35
|
__exportStar(require("./publish/base-process-publish-assortment"), exports);
|
|
37
36
|
__exportStar(require("./publish/base-process-publish-assortment-callback"), exports);
|
|
38
37
|
__exportStar(require("./entity-processor/base-entity-processor"), exports);
|
|
@@ -32,15 +32,6 @@ export declare class BaseProcessPublishAssortment {
|
|
|
32
32
|
skip_await?: undefined;
|
|
33
33
|
}>;
|
|
34
34
|
getPublishInfo(assortmentId: string, assortmentPublishChangeId: string, apcHistory: any, publisher: any): Promise<any>;
|
|
35
|
-
/** Gets the version number of the snapshot that was created for the publish change.
|
|
36
|
-
* But if no snapshot was found for the publish change, and the last snapshot was
|
|
37
|
-
* created before the publish change, then it returns 'after: versionNumber' where
|
|
38
|
-
* versionNumber is the version number of the last snapshot.
|
|
39
|
-
* If no snapshot was found for the publish change, and the last snapshot was
|
|
40
|
-
* created after the publish change, then it returns 'unknown'.
|
|
41
|
-
*
|
|
42
|
-
* @returns versionNumber or 'unknown' or 'after: versionNumber'
|
|
43
|
-
*/
|
|
44
35
|
getSnapshotVersion(assortment: any, apc: any): Promise<number | string>;
|
|
45
36
|
getSeasonFederation(assortmentId: any): Promise<SeasonFederation>;
|
|
46
37
|
getAssortment(assortmentId: any): Promise<any>;
|
|
@@ -91,22 +82,6 @@ export declare class BaseProcessPublishAssortment {
|
|
|
91
82
|
private getCurrentDateString;
|
|
92
83
|
getItemFamilyChanges(pcd: PublishChangeData, changeDetail: any, assortmentItemFullChangeMap: Map<string, any>, assortmentItemDeleteMap: Map<string, any>): Map<string, ItemFamilyChanges>;
|
|
93
84
|
getEventsForPublishChangeData(publishChangeData: PublishChangeData): Promise<SeasonalPayload[]>;
|
|
94
|
-
/**Returns the events for a given ItemFamilyChanges object
|
|
95
|
-
*
|
|
96
|
-
* Cases:
|
|
97
|
-
* Add just family:
|
|
98
|
-
* Add option to family (with existing option):
|
|
99
|
-
* Add option to family (no options on assortment):
|
|
100
|
-
* Remove family and option:
|
|
101
|
-
* Remove only option and leave family:
|
|
102
|
-
* Remove one option of multiple for family:
|
|
103
|
-
*
|
|
104
|
-
* @param itemFamilyChanges
|
|
105
|
-
* @param assortmentId
|
|
106
|
-
* @param assortmentFederationId
|
|
107
|
-
* @param itemToFederatedIdMapping
|
|
108
|
-
* @returns
|
|
109
|
-
*/
|
|
110
85
|
getEventsForItemFamilyChanges(itemFamilyChanges: ItemFamilyChanges, assortmentId: string, seasonFed: SeasonFederation, itemToFederatedIdMapping: Map<string, string>): Promise<SeasonalPayload[]>;
|
|
111
86
|
getProjectItem(itemFamilyChanges: ItemFamilyChanges, id: string): any;
|
|
112
87
|
getSeasonalData(projectItem: any): Promise<object>;
|
|
@@ -13,7 +13,7 @@ const app_framework_1 = require("@contrail/app-framework");
|
|
|
13
13
|
const event_short_message_status_1 = require("../util/event-short-message-status");
|
|
14
14
|
class BaseProcessPublishAssortment {
|
|
15
15
|
constructor(_config, _dc, _mapFileUtil) {
|
|
16
|
-
this.TTL = 30 * 24 * 60 * 60 * 1000;
|
|
16
|
+
this.TTL = 30 * 24 * 60 * 60 * 1000;
|
|
17
17
|
this.cache = {
|
|
18
18
|
carriedFromSeason: {}
|
|
19
19
|
};
|
|
@@ -52,14 +52,13 @@ class BaseProcessPublishAssortment {
|
|
|
52
52
|
}
|
|
53
53
|
apcHistory = await this.getApcHistory(assortmentId);
|
|
54
54
|
const sinceDate = await this.getSinceDate(assortmentId, assortmentPublishChangeId, apcHistory);
|
|
55
|
-
//Get detail information
|
|
56
55
|
const assortmentPublishChange = await this.downloadAssortmentPublishChange(assortmentId, assortmentPublishChangeId);
|
|
57
56
|
publisher = this.getPublisher(assortmentPublishChange);
|
|
58
57
|
const changeDetail = await this.downloadHydratedChangeDetail(assortmentPublishChange);
|
|
59
58
|
const assortmentBaseline = await this.downloadAssortmentBaseline(assortmentPublishChange);
|
|
60
59
|
const deleteChanges = await this.getDeleteChanges(assortmentPublishChange, apcHistory, assortmentBaseline, sinceDate);
|
|
61
60
|
const releasedForDevelopmentItemIds = this.getReleasedForDevelopmentItemAndFamilyIds(assortmentBaseline, deleteChanges);
|
|
62
|
-
const itemToFederatedIdMapping = await this.getItemFederatedIds(
|
|
61
|
+
const itemToFederatedIdMapping = await this.getItemFederatedIds();
|
|
63
62
|
const pcd = new publish_change_data_1.PublishChangeData(assortmentId, seasonFed, assortmentPublishChangeId, sinceDate, publisher);
|
|
64
63
|
pcd.itemToFederatedIdMapping = itemToFederatedIdMapping;
|
|
65
64
|
pcd.releasedForDevelopmentItemIds = releasedForDevelopmentItemIds;
|
|
@@ -95,15 +94,6 @@ class BaseProcessPublishAssortment {
|
|
|
95
94
|
};
|
|
96
95
|
return publishInfo;
|
|
97
96
|
}
|
|
98
|
-
/** Gets the version number of the snapshot that was created for the publish change.
|
|
99
|
-
* But if no snapshot was found for the publish change, and the last snapshot was
|
|
100
|
-
* created before the publish change, then it returns 'after: versionNumber' where
|
|
101
|
-
* versionNumber is the version number of the last snapshot.
|
|
102
|
-
* If no snapshot was found for the publish change, and the last snapshot was
|
|
103
|
-
* created after the publish change, then it returns 'unknown'.
|
|
104
|
-
*
|
|
105
|
-
* @returns versionNumber or 'unknown' or 'after: versionNumber'
|
|
106
|
-
*/
|
|
107
97
|
async getSnapshotVersion(assortment, apc) {
|
|
108
98
|
const entityReference = assortment?.createdForReference;
|
|
109
99
|
const createdOnString = apc?.createdOn;
|
|
@@ -111,7 +101,7 @@ class BaseProcessPublishAssortment {
|
|
|
111
101
|
return 'unknown';
|
|
112
102
|
}
|
|
113
103
|
const createdOnDate = new Date(createdOnString);
|
|
114
|
-
createdOnDate.setMonth(createdOnDate.getMonth() - 1);
|
|
104
|
+
createdOnDate.setMonth(createdOnDate.getMonth() - 1);
|
|
115
105
|
const createdOnStringMinus1 = createdOnDate.toISOString();
|
|
116
106
|
const createdOn = 'ISGREATERTHAN ' + createdOnStringMinus1;
|
|
117
107
|
const snapshots = await new sdk_1.Entities().get({
|
|
@@ -358,7 +348,6 @@ class BaseProcessPublishAssortment {
|
|
|
358
348
|
console.info('sinceDateMilliseconds: ' + sinceDateMilliseconds);
|
|
359
349
|
console.info('apcDateMilliseconds: ' + previousApcDate);
|
|
360
350
|
}
|
|
361
|
-
//if only 1 apc, no processing needed
|
|
362
351
|
if (sinceDateMilliseconds !== previousApcDate) {
|
|
363
352
|
console.info('sinceDateMilliseconds !== apcDateMilliseconds');
|
|
364
353
|
const currentAssortmentItemIds = this.getBaselineItemIds(assortmentBaseline);
|
|
@@ -444,27 +433,12 @@ class BaseProcessPublishAssortment {
|
|
|
444
433
|
previousBaseline = await this.downloadAssortmentBaseline(previousApc);
|
|
445
434
|
}
|
|
446
435
|
const deleteIds = apc?.detail?.deletes.map(dItem => dItem?.id);
|
|
447
|
-
//building deletes based on previous baseline; because some APCs don't have delete data
|
|
448
436
|
const deleteArray = previousBaseline?.assortmentItems.filter(aItem => deleteIds.includes(aItem?.itemId));
|
|
449
437
|
console.info('deleteArray.length: ' + deleteArray.length);
|
|
450
438
|
return deleteArray;
|
|
451
439
|
}
|
|
452
|
-
async getItemFederatedIds(
|
|
440
|
+
async getItemFederatedIds() {
|
|
453
441
|
const itemFederatedIds = new Map();
|
|
454
|
-
// const expandedItemIds = itemIds.map(id => 'item:' + id);
|
|
455
|
-
// const fedRecords = await new Federation(this.logger).getFederationRecordsFromIdsBulk(expandedItemIds);
|
|
456
|
-
// for (let i = 0; i < fedRecords.length; i++) {
|
|
457
|
-
// const federationRecord = fedRecords[i];
|
|
458
|
-
// // console.log('federationRecord: ' + JSON.stringify(federationRecord));
|
|
459
|
-
// // console.log('federationRecord.reference: ' + federationRecord.reference);
|
|
460
|
-
// // console.log('federationRecord.mappedReference: ' + federationRecord.mappedReference);
|
|
461
|
-
// let vibeId = federationRecord.reference;
|
|
462
|
-
// if (vibeId && vibeId.startsWith('item:')) {
|
|
463
|
-
// vibeId = vibeId.substring(5);
|
|
464
|
-
// }
|
|
465
|
-
// itemFederatedIds.set(vibeId, federationRecord.mappedReference);
|
|
466
|
-
// }
|
|
467
|
-
// console.log('itemFederatedIds: ' + JSON.stringify(Object.fromEntries(itemFederatedIds)));
|
|
468
442
|
return itemFederatedIds;
|
|
469
443
|
}
|
|
470
444
|
getFullChangeAssortmentMap(fullChange) {
|
|
@@ -591,7 +565,7 @@ class BaseProcessPublishAssortment {
|
|
|
591
565
|
case 'vibeiqfile-dontsendtoflexplm':
|
|
592
566
|
return this.handleVibeIQFile(events, eventType, sendMode);
|
|
593
567
|
default:
|
|
594
|
-
return {};
|
|
568
|
+
return {};
|
|
595
569
|
}
|
|
596
570
|
}
|
|
597
571
|
async sendToFlexPLM(events, eventType) {
|
|
@@ -761,7 +735,7 @@ class BaseProcessPublishAssortment {
|
|
|
761
735
|
else {
|
|
762
736
|
ifc.colorDeletes.push(itemId);
|
|
763
737
|
}
|
|
764
|
-
}
|
|
738
|
+
}
|
|
765
739
|
if (app_framework_1.Logger.isDebugOn()) {
|
|
766
740
|
console.debug('returning size: ' + itemFamilyChanges.size);
|
|
767
741
|
for (const [key, value] of itemFamilyChanges) {
|
|
@@ -781,22 +755,6 @@ class BaseProcessPublishAssortment {
|
|
|
781
755
|
}
|
|
782
756
|
return seasonalPayloads;
|
|
783
757
|
}
|
|
784
|
-
/**Returns the events for a given ItemFamilyChanges object
|
|
785
|
-
*
|
|
786
|
-
* Cases:
|
|
787
|
-
* Add just family:
|
|
788
|
-
* Add option to family (with existing option):
|
|
789
|
-
* Add option to family (no options on assortment):
|
|
790
|
-
* Remove family and option:
|
|
791
|
-
* Remove only option and leave family:
|
|
792
|
-
* Remove one option of multiple for family:
|
|
793
|
-
*
|
|
794
|
-
* @param itemFamilyChanges
|
|
795
|
-
* @param assortmentId
|
|
796
|
-
* @param assortmentFederationId
|
|
797
|
-
* @param itemToFederatedIdMapping
|
|
798
|
-
* @returns
|
|
799
|
-
*/
|
|
800
758
|
async getEventsForItemFamilyChanges(itemFamilyChanges, assortmentId, seasonFed, itemToFederatedIdMapping) {
|
|
801
759
|
console.info('getEventsForItemFamilyChanges()');
|
|
802
760
|
const events = [];
|
|
@@ -806,10 +764,7 @@ class BaseProcessPublishAssortment {
|
|
|
806
764
|
const familyAssortmentItem = itemFamilyChanges.familyAdd || itemFamilyChanges.familyUpdate || itemFamilyChanges.familyDelete
|
|
807
765
|
|| itemFamilyChanges.colorAdds.length > 0 || itemFamilyChanges.colorUpdates.length > 0 || itemFamilyChanges.colorDeletes.length > 0
|
|
808
766
|
|| (projectItem && this.updatedSinceDate(projectItem, itemFamilyChanges.sinceDate));
|
|
809
|
-
//familyItemRemoved is used when adding the first option to an assortment
|
|
810
|
-
//and will have updates for the family item.
|
|
811
767
|
if (familyAssortmentItem) {
|
|
812
|
-
//Product-season add
|
|
813
768
|
const entityReference = itemFamilyChanges.itemFamilyId;
|
|
814
769
|
const prodEntityData = (itemFamilyChanges.assortmentItemFullChangeMap.has(entityReference))
|
|
815
770
|
? itemFamilyChanges.assortmentItemFullChangeMap.get(entityReference)?.item
|
|
@@ -835,9 +790,6 @@ class BaseProcessPublishAssortment {
|
|
|
835
790
|
}
|
|
836
791
|
events.push(psUpsert);
|
|
837
792
|
}
|
|
838
|
-
//colorway-season adds
|
|
839
|
-
//colorAdds
|
|
840
|
-
//colorUpdates
|
|
841
793
|
const colorwayChanges = [];
|
|
842
794
|
colorwayChanges.push(...itemFamilyChanges.colorAdds);
|
|
843
795
|
colorwayChanges.push(...itemFamilyChanges.colorUpdates);
|
|
@@ -878,9 +830,6 @@ class BaseProcessPublishAssortment {
|
|
|
878
830
|
const aItem = itemFamilyChanges?.assortmentItemFullChangeMap.get(id);
|
|
879
831
|
projectItem = aItem?.projectItem;
|
|
880
832
|
}
|
|
881
|
-
/////////////////////////////////////////////////////////////////////////////
|
|
882
|
-
//Get from option assortmentItem because family not in assortmentItemFullChangeMap:start
|
|
883
|
-
/////////////////////////////////////////////////////////////////////////////
|
|
884
833
|
if (id === itemFamilyChanges.itemFamilyId && Object.keys(projectItem).length == 0) {
|
|
885
834
|
for (const asstItem of itemFamilyChanges.assortmentItemFullChangeMap.values()) {
|
|
886
835
|
if (asstItem?.familyProjectItem) {
|
|
@@ -889,9 +838,6 @@ class BaseProcessPublishAssortment {
|
|
|
889
838
|
}
|
|
890
839
|
}
|
|
891
840
|
}
|
|
892
|
-
/////////////////////////////////////////////////////////////////////////////
|
|
893
|
-
//Get from option assortmentItem because family not in assortmentItemFullChangeMap:end
|
|
894
|
-
/////////////////////////////////////////////////////////////////////////////
|
|
895
841
|
return projectItem;
|
|
896
842
|
}
|
|
897
843
|
async getSeasonalData(projectItem) {
|