@contrail/flexplm 1.7.4-alpha.7bbda17 → 1.7.4-alpha.aaaa660
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.
|
@@ -79,7 +79,7 @@ class ConfigCreateCommand {
|
|
|
79
79
|
}
|
|
80
80
|
fs.writeFileSync(outPath, rendered, 'utf8');
|
|
81
81
|
console.log(`Created ${outPath}`);
|
|
82
|
-
console.log('
|
|
82
|
+
console.log('"orgName" and "appIdentifier" are pre-filled, but this file is not complete yet: FlexPLM connectivity also requires apiHost, userName, and password. See the "_availableAttributes" block in the file for these and other attributes this org can set (identifierAtts, LCSMaterial, etc.) — add the ones you need as real top-level keys, then delete "_availableAttributes"; the connector ignores it and applies defaults at runtime for anything you omit.');
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
exports.ConfigCreateCommand = ConfigCreateCommand;
|
|
@@ -59,6 +59,11 @@ describe('ConfigCreateCommand', () => {
|
|
|
59
59
|
expect(config.orgName).toEqual('acme');
|
|
60
60
|
expect(config.appIdentifier).toEqual('@vibeiq/flexplm-connector');
|
|
61
61
|
});
|
|
62
|
+
it('trims whitespace around the orgName input', async () => {
|
|
63
|
+
answers = [' acme ', '@vibeiq/flexplm-connector'];
|
|
64
|
+
await new config_create_1.ConfigCreateCommand().run();
|
|
65
|
+
expect(fs.existsSync(path.join(tempDir, 'acme-flexplmConfig.json'))).toBe(true);
|
|
66
|
+
});
|
|
62
67
|
it('defaults appIdentifier to @vibeiq/flexplm-connector when left blank', async () => {
|
|
63
68
|
answers = ['acme', ''];
|
|
64
69
|
await new config_create_1.ConfigCreateCommand().run();
|
|
@@ -26,32 +26,72 @@ describe('ConfigUploadCommand.parseArgs', () => {
|
|
|
26
26
|
const opts = config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '-b', 'feature/x']);
|
|
27
27
|
expect(opts.branch).toEqual('feature/x');
|
|
28
28
|
});
|
|
29
|
+
it('parses options before the file path', () => {
|
|
30
|
+
const opts = config_upload_1.ConfigUploadCommand.parseArgs(['-m', 'msg', '-b', 'br', 'config.json']);
|
|
31
|
+
expect(opts).toEqual({
|
|
32
|
+
filePath: 'config.json',
|
|
33
|
+
message: 'msg',
|
|
34
|
+
branch: 'br',
|
|
35
|
+
skipGit: false,
|
|
36
|
+
updateConfig: false,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
29
39
|
it('parses --skip-git flag', () => {
|
|
30
40
|
const opts = config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '--skip-git']);
|
|
31
41
|
expect(opts.skipGit).toBe(true);
|
|
32
42
|
});
|
|
43
|
+
it('accepts the legacy --skipGit alias', () => {
|
|
44
|
+
const opts = config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '--skipGit']);
|
|
45
|
+
expect(opts.skipGit).toBe(true);
|
|
46
|
+
});
|
|
33
47
|
it('parses --update-config flag', () => {
|
|
34
48
|
const opts = config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '--update-config']);
|
|
35
49
|
expect(opts.updateConfig).toBe(true);
|
|
36
50
|
});
|
|
51
|
+
it('parses all options together', () => {
|
|
52
|
+
const opts = config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '-m', 'msg', '-b', 'br', '--skip-git', '--update-config']);
|
|
53
|
+
expect(opts).toEqual({
|
|
54
|
+
filePath: 'config.json',
|
|
55
|
+
message: 'msg',
|
|
56
|
+
branch: 'br',
|
|
57
|
+
skipGit: true,
|
|
58
|
+
updateConfig: true,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
37
61
|
it('throws when -m is missing its value', () => {
|
|
38
62
|
expect(() => config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '-m'])).toThrow(/-m requires a commit message/);
|
|
39
63
|
});
|
|
64
|
+
it('throws when -b is missing its value', () => {
|
|
65
|
+
expect(() => config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '-b'])).toThrow(/-b requires a branch name/);
|
|
66
|
+
});
|
|
40
67
|
it('throws on unknown option', () => {
|
|
41
68
|
expect(() => config_upload_1.ConfigUploadCommand.parseArgs(['config.json', '--bogus'])).toThrow(/Unknown option: --bogus/);
|
|
42
69
|
});
|
|
70
|
+
it('throws when an extra positional argument is supplied', () => {
|
|
71
|
+
expect(() => config_upload_1.ConfigUploadCommand.parseArgs(['config.json', 'extra.json'])).toThrow(/Unexpected argument: extra\.json/);
|
|
72
|
+
});
|
|
43
73
|
it('throws when no file path is provided', () => {
|
|
44
74
|
expect(() => config_upload_1.ConfigUploadCommand.parseArgs([])).toThrow(/missing <path\.json>/);
|
|
45
75
|
});
|
|
76
|
+
it('throws when only options are provided', () => {
|
|
77
|
+
expect(() => config_upload_1.ConfigUploadCommand.parseArgs(['--skip-git'])).toThrow(/missing <path\.json>/);
|
|
78
|
+
});
|
|
46
79
|
});
|
|
47
80
|
describe('ConfigUploadCommand.buildCommitMessage', () => {
|
|
48
81
|
it('appends fileId to the first line of a single-line message', () => {
|
|
49
82
|
expect(config_upload_1.ConfigUploadCommand.buildCommitMessage('initial commit', 'abc123')).toEqual('initial commit [fileId: abc123]');
|
|
50
83
|
});
|
|
84
|
+
it('only appends fileId to the first line of a multi-line message', () => {
|
|
85
|
+
const result = config_upload_1.ConfigUploadCommand.buildCommitMessage('header line\nbody line 1\nbody line 2', 'xyz');
|
|
86
|
+
expect(result).toEqual('header line [fileId: xyz]\nbody line 1\nbody line 2');
|
|
87
|
+
});
|
|
51
88
|
it('handles CRLF line endings', () => {
|
|
52
89
|
const result = config_upload_1.ConfigUploadCommand.buildCommitMessage('header\r\nbody', 'fid');
|
|
53
90
|
expect(result).toEqual('header [fileId: fid]\nbody');
|
|
54
91
|
});
|
|
92
|
+
it('handles an empty message', () => {
|
|
93
|
+
expect(config_upload_1.ConfigUploadCommand.buildCommitMessage('', 'fid')).toEqual(' [fileId: fid]');
|
|
94
|
+
});
|
|
55
95
|
});
|
|
56
96
|
describe('ConfigUploadCommand.run', () => {
|
|
57
97
|
const fs = require('fs');
|
|
@@ -4,19 +4,27 @@
|
|
|
4
4
|
|
|
5
5
|
"_availableAttributes": {
|
|
6
6
|
"_note": "Reference only — the connector never reads this key. Add any of the attributes below as real top-level keys if this org needs them, then delete this whole \"_availableAttributes\" block.",
|
|
7
|
-
"apiHost": "FlexPLM API host base URL
|
|
8
|
-
"userName": "FlexPLM user name used for Basic Auth (
|
|
9
|
-
"password": "FlexPLM password used for Basic Auth (
|
|
10
|
-
"plmEnviornment": "Sent as the PLM_ENV header on every FlexPLM request",
|
|
7
|
+
"apiHost": "FlexPLM API host base URL. Required — throws NEED_CONFIG_VALUES if missing",
|
|
8
|
+
"userName": "FlexPLM user name used for Basic Auth. Required; rewritten to a () => string getter",
|
|
9
|
+
"password": "FlexPLM password used for Basic Auth. Required; rewritten to a () => string getter",
|
|
11
10
|
"urlContext": "Path prefix for FlexPLM URLs. Default: '/Windchill'",
|
|
12
|
-
"csrfEndpoint": "CSRF token endpoint path. Default: '/servlet/rest/security/csrf'",
|
|
13
|
-
"vibeEventEndpoint": "Endpoint VibeIQ posts inbound events to. Default: '/rfa/vibeiq/vibeEvents'",
|
|
14
11
|
"itemPreDevelopmentLifecycleStages": "Item lifecycle stages during which items are not synced to FlexPLM. Default: ['concept']",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
12
|
+
"logLevel": "Possible values: error/warn/info/debug. Default: info",
|
|
13
|
+
"identifierAtts": "Deprecated. Map of FlexPLM object class to identifier attribute name(s), e.g. { \"LCSProduct\": [\"itemNumber\"] }",
|
|
14
|
+
"plmEnviornment": "Sent as the PLM_ENV header on every FlexPLM request. Only used by 1 customer. NOTE: this key is intentionally spelled \"plmEnviornment\" (matching the connector's actual config key) — do not \"fix\" the spelling to \"plmEnvironment\", it will silently stop working",
|
|
15
|
+
"propertyMapping": "Deprecated. Reserved for custom property-mapping overrides",
|
|
16
|
+
"complexConfig": "Object of additional attributes (see below) merged onto the top level of the config, then deleted; __proto__/constructor/prototype keys are stripped for safety. e.g. { \"complexConfig\": { \"csrfEndpoint\": \"...\" } }",
|
|
17
|
+
"csrfEndpoint (in complexConfig)": "CSRF token endpoint path. Default: '/servlet/rest/security/csrf'",
|
|
18
|
+
"dataConverter.useDisplayForEnumerationMatching (in complexConfig)": "Default: false",
|
|
19
|
+
"dataConverter.verboseDebug (in complexConfig)": "Default: false",
|
|
20
|
+
"flexplmConnect.staticHeaders (in complexConfig)": "Extra static headers added to every FlexPLM request",
|
|
21
|
+
"LCSMaterial.processAsItem (in complexConfig)": "true routes LCSMaterial to item:material instead of custom-entity. Default: false",
|
|
22
|
+
"max_thumbnail_size (in complexConfig)": "Max thumbnail size in bytes. Default: 5 MB",
|
|
23
|
+
"payloadDefaultAsArray (in complexConfig)": "Whether outbound payload values default to arrays. Default: true",
|
|
24
|
+
"search.<entityType>.useIdentityServiceForInboundData (in complexConfig)": "entityType is one of: item, color, custom-entity, project-item. Default: false",
|
|
25
|
+
"sendMode.ASYNC_PUBLISH_SEASON (in complexConfig)": "Default: 'vibeiqfile'",
|
|
26
|
+
"syncOptionSets (in complexConfig)": "Array of { flexInternalName, vibeSlug }",
|
|
27
|
+
"useDistinctRestEndPointForImages (in complexConfig)": "Default: false; when true routes image fetch through /rfa/vibeiq/image instead of the raw URL",
|
|
28
|
+
"vibeEventEndpoint (in complexConfig)": "Endpoint VibeIQ posts inbound events to. Default: '/rfa/vibeiq/vibeEvents'"
|
|
21
29
|
}
|
|
22
30
|
}
|