@contrail/flexplm 1.6.1-alpha.75cfe7f → 1.7.0-alpha.71b4d30
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/lib/cli/commands/{create.d.ts → config-file/create.d.ts} +0 -1
- package/lib/cli/commands/config-file/create.js +61 -0
- package/lib/cli/commands/config-file/create.spec.js +74 -0
- package/lib/cli/commands/config-file/index.d.ts +2 -0
- package/lib/cli/commands/config-file/index.js +47 -0
- package/lib/cli/commands/config-file/upload.d.ts +8 -0
- package/lib/cli/commands/config-file/upload.js +84 -0
- package/lib/cli/commands/config-file/upload.spec.js +51 -0
- package/lib/cli/commands/mapping-file/create.d.ts +4 -0
- package/lib/cli/commands/{create.js → mapping-file/create.js} +4 -20
- package/lib/cli/commands/mapping-file/create.spec.d.ts +1 -0
- package/lib/cli/commands/{create.spec.js → mapping-file/create.spec.js} +1 -1
- package/lib/cli/commands/mapping-file/index.d.ts +2 -0
- package/lib/cli/commands/mapping-file/index.js +57 -0
- package/lib/cli/commands/mapping-file/upload.d.ts +3 -0
- package/lib/cli/commands/mapping-file/upload.js +70 -0
- package/lib/cli/commands/shared/git.d.ts +6 -0
- package/lib/cli/commands/shared/git.js +100 -0
- package/lib/cli/commands/shared/prompts.d.ts +2 -0
- package/lib/cli/commands/shared/prompts.js +61 -0
- package/lib/cli/commands/shared/upload-base.d.ts +24 -0
- package/lib/cli/commands/shared/upload-base.js +138 -0
- package/lib/cli/commands/shared/upload-base.spec.d.ts +1 -0
- package/lib/cli/commands/shared/upload-base.spec.js +99 -0
- package/lib/cli/index.js +18 -37
- package/lib/cli/index.spec.js +111 -53
- package/lib/cli/template/config-template.json.template +5 -0
- package/package.json +2 -2
- package/scripts/copy-template.js +16 -5
- package/lib/cli/commands/upload.d.ts +0 -18
- package/lib/cli/commands/upload.js +0 -251
- package/lib/cli/commands/upload.spec.js +0 -95
- /package/lib/cli/commands/{create.spec.d.ts → config-file/create.spec.d.ts} +0 -0
- /package/lib/cli/commands/{upload.spec.d.ts → config-file/upload.spec.d.ts} +0 -0
- /package/lib/cli/commands/{compile.d.ts → mapping-file/compile.d.ts} +0 -0
- /package/lib/cli/commands/{compile.js → mapping-file/compile.js} +0 -0
- /package/lib/cli/commands/{compile.spec.d.ts → mapping-file/compile.spec.d.ts} +0 -0
- /package/lib/cli/commands/{compile.spec.js → mapping-file/compile.spec.js} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.CreateCommand = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const prompts_1 = require("../shared/prompts");
|
|
30
|
+
const TEMPLATE_FILENAME = 'config-template.json.template';
|
|
31
|
+
const PLACEHOLDER = '<ORG_NAME>';
|
|
32
|
+
class CreateCommand {
|
|
33
|
+
findTemplate() {
|
|
34
|
+
const candidates = [
|
|
35
|
+
path.join(__dirname, '..', '..', 'template', TEMPLATE_FILENAME),
|
|
36
|
+
path.join(__dirname, '..', '..', '..', '..', 'src', 'cli', 'template', TEMPLATE_FILENAME),
|
|
37
|
+
];
|
|
38
|
+
for (const candidate of candidates) {
|
|
39
|
+
if (fs.existsSync(candidate)) {
|
|
40
|
+
return candidate;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Could not locate ${TEMPLATE_FILENAME}. Tried:\n ${candidates.join('\n ')}`);
|
|
44
|
+
}
|
|
45
|
+
async run() {
|
|
46
|
+
const orgName = (await (0, prompts_1.prompt)('orgName: ')).trim();
|
|
47
|
+
if (!orgName) {
|
|
48
|
+
throw new Error('orgName is required');
|
|
49
|
+
}
|
|
50
|
+
const templatePath = this.findTemplate();
|
|
51
|
+
const templateBody = fs.readFileSync(templatePath, 'utf8');
|
|
52
|
+
const rendered = templateBody.split(PLACEHOLDER).join(orgName);
|
|
53
|
+
const outPath = path.resolve(process.cwd(), `${orgName}-config.json`);
|
|
54
|
+
if (fs.existsSync(outPath)) {
|
|
55
|
+
throw new Error(`Refusing to overwrite existing file: ${outPath}`);
|
|
56
|
+
}
|
|
57
|
+
fs.writeFileSync(outPath, rendered, 'utf8');
|
|
58
|
+
console.log(`Created ${outPath}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.CreateCommand = CreateCommand;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const fs = __importStar(require("fs"));
|
|
27
|
+
const os = __importStar(require("os"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
let nextAnswer = '';
|
|
30
|
+
jest.mock('readline', () => ({
|
|
31
|
+
createInterface: () => ({
|
|
32
|
+
question: (_q, cb) => cb(nextAnswer),
|
|
33
|
+
close: () => { },
|
|
34
|
+
}),
|
|
35
|
+
}));
|
|
36
|
+
const create_1 = require("./create");
|
|
37
|
+
describe('runCreate (config-file)', () => {
|
|
38
|
+
let tempDir;
|
|
39
|
+
let originalCwd;
|
|
40
|
+
let logSpy;
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
originalCwd = process.cwd();
|
|
43
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'flexplm-config-create-'));
|
|
44
|
+
process.chdir(tempDir);
|
|
45
|
+
logSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
46
|
+
nextAnswer = '';
|
|
47
|
+
});
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
logSpy.mockRestore();
|
|
50
|
+
process.chdir(originalCwd);
|
|
51
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
52
|
+
});
|
|
53
|
+
it('writes <orgName>-config.json with the placeholder replaced and valid JSON envelope', async () => {
|
|
54
|
+
nextAnswer = 'acme';
|
|
55
|
+
await new create_1.CreateCommand().run();
|
|
56
|
+
const outPath = path.join(tempDir, 'acme-config.json');
|
|
57
|
+
expect(fs.existsSync(outPath)).toBe(true);
|
|
58
|
+
const parsed = JSON.parse(fs.readFileSync(outPath, 'utf8'));
|
|
59
|
+
expect(parsed.orgName).toEqual('acme');
|
|
60
|
+
expect(parsed.appIdentifier).toEqual('@vibeiq/flexplm-connector');
|
|
61
|
+
expect(parsed.config).toEqual({});
|
|
62
|
+
});
|
|
63
|
+
it('throws when orgName is empty', async () => {
|
|
64
|
+
nextAnswer = ' ';
|
|
65
|
+
await expect(new create_1.CreateCommand().run()).rejects.toThrow(/orgName is required/);
|
|
66
|
+
});
|
|
67
|
+
it('refuses to overwrite an existing file', async () => {
|
|
68
|
+
const existing = path.join(tempDir, 'acme-config.json');
|
|
69
|
+
fs.writeFileSync(existing, 'do not clobber', 'utf8');
|
|
70
|
+
nextAnswer = 'acme';
|
|
71
|
+
await expect(new create_1.CreateCommand().run()).rejects.toThrow(/Refusing to overwrite/);
|
|
72
|
+
expect(fs.readFileSync(existing, 'utf8')).toEqual('do not clobber');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const CONFIG_FILE_USAGE = "Usage: flexplm config-file <command> [args]\n\nCommands:\n create Scaffold a new <orgName>-config.json file in the current directory\n upload <path.json> [opts] Upload the inner \"config\" payload of a config JSON file to VibeIQ\n\nUpload options:\n -m <message> Git commit message (prompted if omitted)\n -b <branch> Create a new git branch before committing\n --skip-git Skip the post-upload git commit (default: commit)\n --update-config Patch the app-org appConfig.configFile with the uploaded file ID without needing to paste into the admin console\n\nEnvironment (upload):\n CONTRAIL_CLI_EMAIL VibeIQ user email\n CONTRAIL_CLI_PASSWORD VibeIQ user password\n";
|
|
2
|
+
export declare function runConfigFile(subcommand: string | undefined, rest: string[]): Promise<void>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runConfigFile = exports.CONFIG_FILE_USAGE = void 0;
|
|
4
|
+
const create_1 = require("./create");
|
|
5
|
+
const upload_1 = require("./upload");
|
|
6
|
+
exports.CONFIG_FILE_USAGE = `Usage: flexplm config-file <command> [args]
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
create Scaffold a new <orgName>-config.json file in the current directory
|
|
10
|
+
upload <path.json> [opts] Upload the inner "config" payload of a config JSON file to VibeIQ
|
|
11
|
+
|
|
12
|
+
Upload options:
|
|
13
|
+
-m <message> Git commit message (prompted if omitted)
|
|
14
|
+
-b <branch> Create a new git branch before committing
|
|
15
|
+
--skip-git Skip the post-upload git commit (default: commit)
|
|
16
|
+
--update-config Patch the app-org appConfig.configFile with the uploaded file ID without needing to paste into the admin console
|
|
17
|
+
|
|
18
|
+
Environment (upload):
|
|
19
|
+
CONTRAIL_CLI_EMAIL VibeIQ user email
|
|
20
|
+
CONTRAIL_CLI_PASSWORD VibeIQ user password
|
|
21
|
+
`;
|
|
22
|
+
async function runConfigFile(subcommand, rest) {
|
|
23
|
+
switch (subcommand) {
|
|
24
|
+
case 'create':
|
|
25
|
+
await new create_1.CreateCommand().run();
|
|
26
|
+
return;
|
|
27
|
+
case 'upload':
|
|
28
|
+
if (!rest[0]) {
|
|
29
|
+
console.error('config-file upload: missing <path.json> argument');
|
|
30
|
+
console.error(exports.CONFIG_FILE_USAGE);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
await new upload_1.UploadCommand().run(rest);
|
|
34
|
+
return;
|
|
35
|
+
case undefined:
|
|
36
|
+
case '-h':
|
|
37
|
+
case '--help':
|
|
38
|
+
case 'help':
|
|
39
|
+
console.log(exports.CONFIG_FILE_USAGE);
|
|
40
|
+
return;
|
|
41
|
+
default:
|
|
42
|
+
console.error(`Unknown config-file subcommand: ${subcommand}`);
|
|
43
|
+
console.error(exports.CONFIG_FILE_USAGE);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.runConfigFile = runConfigFile;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.UploadCommand = exports.parseConfigEnvelope = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const upload_base_1 = require("../shared/upload-base");
|
|
30
|
+
function parseConfigEnvelope(jsonAbsPath, raw) {
|
|
31
|
+
let parsed;
|
|
32
|
+
try {
|
|
33
|
+
parsed = JSON.parse(raw);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
throw new Error(`Failed to parse JSON in ${jsonAbsPath}: ${err && err.message ? err.message : err}`);
|
|
37
|
+
}
|
|
38
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
39
|
+
throw new Error(`Config file must be a JSON object: ${jsonAbsPath}`);
|
|
40
|
+
}
|
|
41
|
+
const envelope = parsed;
|
|
42
|
+
const orgName = envelope.orgName;
|
|
43
|
+
if (typeof orgName !== 'string' || !orgName) {
|
|
44
|
+
throw new Error(`Config file is missing string "orgName": ${jsonAbsPath}`);
|
|
45
|
+
}
|
|
46
|
+
const appIdentifier = envelope.appIdentifier;
|
|
47
|
+
if (typeof appIdentifier !== 'string' || !appIdentifier) {
|
|
48
|
+
throw new Error(`Config file is missing string "appIdentifier": ${jsonAbsPath}`);
|
|
49
|
+
}
|
|
50
|
+
const config = envelope.config;
|
|
51
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
52
|
+
throw new Error(`Config file is missing object "config": ${jsonAbsPath}`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
orgName,
|
|
56
|
+
appIdentifier,
|
|
57
|
+
config: config,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
exports.parseConfigEnvelope = parseConfigEnvelope;
|
|
61
|
+
const configStrategy = {
|
|
62
|
+
topicLabel: 'config-file',
|
|
63
|
+
sourceExtension: '.json',
|
|
64
|
+
async prepare(jsonAbsPath) {
|
|
65
|
+
const raw = fs.readFileSync(jsonAbsPath, 'utf8');
|
|
66
|
+
const { orgName, appIdentifier, config } = parseConfigEnvelope(jsonAbsPath, raw);
|
|
67
|
+
const uploadBuffer = Buffer.from(JSON.stringify(config, null, 2), 'utf8');
|
|
68
|
+
return {
|
|
69
|
+
orgName,
|
|
70
|
+
appIdentifier,
|
|
71
|
+
uploadBuffer,
|
|
72
|
+
uploadFileName: path.basename(jsonAbsPath),
|
|
73
|
+
uploadContentType: 'application/json',
|
|
74
|
+
configPropertyName: 'configFile',
|
|
75
|
+
filesToCommit: [jsonAbsPath],
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
class UploadCommand {
|
|
80
|
+
async run(args) {
|
|
81
|
+
await (0, upload_base_1.runUpload)(configStrategy, args);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.UploadCommand = UploadCommand;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
jest.mock('@contrail/sdk', () => ({
|
|
4
|
+
Entities: jest.fn(),
|
|
5
|
+
Files: jest.fn(),
|
|
6
|
+
login: jest.fn(),
|
|
7
|
+
}));
|
|
8
|
+
const upload_1 = require("./upload");
|
|
9
|
+
describe('parseConfigEnvelope', () => {
|
|
10
|
+
const file = '/tmp/sample-config.json';
|
|
11
|
+
it('parses a well-formed envelope', () => {
|
|
12
|
+
const raw = JSON.stringify({
|
|
13
|
+
orgName: 'acme',
|
|
14
|
+
appIdentifier: '@vibeiq/flexplm-connector',
|
|
15
|
+
config: { LCSMaterial: { processAsItem: true } },
|
|
16
|
+
});
|
|
17
|
+
const result = (0, upload_1.parseConfigEnvelope)(file, raw);
|
|
18
|
+
expect(result).toEqual({
|
|
19
|
+
orgName: 'acme',
|
|
20
|
+
appIdentifier: '@vibeiq/flexplm-connector',
|
|
21
|
+
config: { LCSMaterial: { processAsItem: true } },
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it('throws on invalid JSON', () => {
|
|
25
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, '{not valid json')).toThrow(/Failed to parse JSON/);
|
|
26
|
+
});
|
|
27
|
+
it('throws when the top-level value is not an object', () => {
|
|
28
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, '[]')).toThrow(/must be a JSON object/);
|
|
29
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, '"hello"')).toThrow(/must be a JSON object/);
|
|
30
|
+
});
|
|
31
|
+
it('throws when orgName is missing', () => {
|
|
32
|
+
const raw = JSON.stringify({ appIdentifier: '@vibeiq/flexplm-connector', config: {} });
|
|
33
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, raw)).toThrow(/missing string "orgName"/);
|
|
34
|
+
});
|
|
35
|
+
it('throws when orgName is empty', () => {
|
|
36
|
+
const raw = JSON.stringify({ orgName: '', appIdentifier: '@vibeiq/flexplm-connector', config: {} });
|
|
37
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, raw)).toThrow(/missing string "orgName"/);
|
|
38
|
+
});
|
|
39
|
+
it('throws when appIdentifier is missing', () => {
|
|
40
|
+
const raw = JSON.stringify({ orgName: 'acme', config: {} });
|
|
41
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, raw)).toThrow(/missing string "appIdentifier"/);
|
|
42
|
+
});
|
|
43
|
+
it('throws when config is missing', () => {
|
|
44
|
+
const raw = JSON.stringify({ orgName: 'acme', appIdentifier: '@vibeiq/flexplm-connector' });
|
|
45
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, raw)).toThrow(/missing object "config"/);
|
|
46
|
+
});
|
|
47
|
+
it('throws when config is not an object', () => {
|
|
48
|
+
const raw = JSON.stringify({ orgName: 'acme', appIdentifier: '@vibeiq/flexplm-connector', config: [] });
|
|
49
|
+
expect(() => (0, upload_1.parseConfigEnvelope)(file, raw)).toThrow(/missing object "config"/);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -26,30 +26,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.CreateCommand = void 0;
|
|
27
27
|
const fs = __importStar(require("fs"));
|
|
28
28
|
const path = __importStar(require("path"));
|
|
29
|
-
const
|
|
29
|
+
const prompts_1 = require("../shared/prompts");
|
|
30
30
|
const TEMPLATE_FILENAME = 'mapping-template.ts.template';
|
|
31
31
|
const PLACEHOLDER = '<ORG_NAME>';
|
|
32
32
|
class CreateCommand {
|
|
33
|
-
prompt(question) {
|
|
34
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
35
|
-
const onSigint = () => {
|
|
36
|
-
rl.close();
|
|
37
|
-
process.stdout.write('\n');
|
|
38
|
-
process.exit(130);
|
|
39
|
-
};
|
|
40
|
-
process.once('SIGINT', onSigint);
|
|
41
|
-
return new Promise((resolve) => {
|
|
42
|
-
rl.question(question, (answer) => {
|
|
43
|
-
process.removeListener('SIGINT', onSigint);
|
|
44
|
-
rl.close();
|
|
45
|
-
resolve(answer);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
33
|
findTemplate() {
|
|
50
34
|
const candidates = [
|
|
51
|
-
path.join(__dirname, '..', 'template', TEMPLATE_FILENAME),
|
|
52
|
-
path.join(__dirname, '..', '..', '..', 'src', 'cli', 'template', TEMPLATE_FILENAME),
|
|
35
|
+
path.join(__dirname, '..', '..', 'template', TEMPLATE_FILENAME),
|
|
36
|
+
path.join(__dirname, '..', '..', '..', '..', 'src', 'cli', 'template', TEMPLATE_FILENAME),
|
|
53
37
|
];
|
|
54
38
|
for (const candidate of candidates) {
|
|
55
39
|
if (fs.existsSync(candidate)) {
|
|
@@ -59,7 +43,7 @@ class CreateCommand {
|
|
|
59
43
|
throw new Error(`Could not locate ${TEMPLATE_FILENAME}. Tried:\n ${candidates.join('\n ')}`);
|
|
60
44
|
}
|
|
61
45
|
async run() {
|
|
62
|
-
const orgName = (await
|
|
46
|
+
const orgName = (await (0, prompts_1.prompt)('orgName: ')).trim();
|
|
63
47
|
if (!orgName) {
|
|
64
48
|
throw new Error('orgName is required');
|
|
65
49
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const MAPPING_FILE_USAGE = "Usage: flexplm mapping-file <command> [args]\n\nCommands:\n create Scaffold a new mapping .ts file in the current directory\n compile <path.ts> Transpile a mapping .ts file to .js alongside it\n upload <path.ts> [opts] Compile a mapping .ts file and upload the resulting .js to VibeIQ\n\nUpload options:\n -m <message> Git commit message (prompted if omitted)\n -b <branch> Create a new git branch before committing\n --skip-git Skip the post-upload git commit (default: commit)\n --update-config Patch the app-org appConfig.transformMapFile with the uploaded file ID without needing to paste into the admin console\n\nEnvironment (upload):\n CONTRAIL_CLI_EMAIL VibeIQ user email\n CONTRAIL_CLI_PASSWORD VibeIQ user password\n";
|
|
2
|
+
export declare function runMappingFile(subcommand: string | undefined, rest: string[]): Promise<void>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runMappingFile = exports.MAPPING_FILE_USAGE = void 0;
|
|
4
|
+
const create_1 = require("./create");
|
|
5
|
+
const compile_1 = require("./compile");
|
|
6
|
+
const upload_1 = require("./upload");
|
|
7
|
+
exports.MAPPING_FILE_USAGE = `Usage: flexplm mapping-file <command> [args]
|
|
8
|
+
|
|
9
|
+
Commands:
|
|
10
|
+
create Scaffold a new mapping .ts file in the current directory
|
|
11
|
+
compile <path.ts> Transpile a mapping .ts file to .js alongside it
|
|
12
|
+
upload <path.ts> [opts] Compile a mapping .ts file and upload the resulting .js to VibeIQ
|
|
13
|
+
|
|
14
|
+
Upload options:
|
|
15
|
+
-m <message> Git commit message (prompted if omitted)
|
|
16
|
+
-b <branch> Create a new git branch before committing
|
|
17
|
+
--skip-git Skip the post-upload git commit (default: commit)
|
|
18
|
+
--update-config Patch the app-org appConfig.transformMapFile with the uploaded file ID without needing to paste into the admin console
|
|
19
|
+
|
|
20
|
+
Environment (upload):
|
|
21
|
+
CONTRAIL_CLI_EMAIL VibeIQ user email
|
|
22
|
+
CONTRAIL_CLI_PASSWORD VibeIQ user password
|
|
23
|
+
`;
|
|
24
|
+
async function runMappingFile(subcommand, rest) {
|
|
25
|
+
switch (subcommand) {
|
|
26
|
+
case 'create':
|
|
27
|
+
await new create_1.CreateCommand().run();
|
|
28
|
+
return;
|
|
29
|
+
case 'compile':
|
|
30
|
+
if (!rest[0]) {
|
|
31
|
+
console.error('mapping-file compile: missing <path.ts> argument');
|
|
32
|
+
console.error(exports.MAPPING_FILE_USAGE);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
await new compile_1.CompileCommand().run(rest[0]);
|
|
36
|
+
return;
|
|
37
|
+
case 'upload':
|
|
38
|
+
if (!rest[0]) {
|
|
39
|
+
console.error('mapping-file upload: missing <path.ts> argument');
|
|
40
|
+
console.error(exports.MAPPING_FILE_USAGE);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
await new upload_1.UploadCommand().run(rest);
|
|
44
|
+
return;
|
|
45
|
+
case undefined:
|
|
46
|
+
case '-h':
|
|
47
|
+
case '--help':
|
|
48
|
+
case 'help':
|
|
49
|
+
console.log(exports.MAPPING_FILE_USAGE);
|
|
50
|
+
return;
|
|
51
|
+
default:
|
|
52
|
+
console.error(`Unknown mapping-file subcommand: ${subcommand}`);
|
|
53
|
+
console.error(exports.MAPPING_FILE_USAGE);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.runMappingFile = runMappingFile;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.UploadCommand = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const upload_base_1 = require("../shared/upload-base");
|
|
30
|
+
const compile_1 = require("./compile");
|
|
31
|
+
const mappingStrategy = {
|
|
32
|
+
topicLabel: 'mapping-file',
|
|
33
|
+
sourceExtension: '.ts',
|
|
34
|
+
async prepare(tsAbsPath) {
|
|
35
|
+
await new compile_1.CompileCommand().run(tsAbsPath);
|
|
36
|
+
const jsAbsPath = tsAbsPath.replace(/\.ts$/, '.js');
|
|
37
|
+
if (!fs.existsSync(jsAbsPath)) {
|
|
38
|
+
throw new Error(`Compiled file not found: ${jsAbsPath}`);
|
|
39
|
+
}
|
|
40
|
+
delete require.cache[jsAbsPath];
|
|
41
|
+
const loaded = require(jsAbsPath);
|
|
42
|
+
const mapping = loaded && loaded.mapping;
|
|
43
|
+
if (!mapping || !mapping.orgInfo) {
|
|
44
|
+
throw new Error(`Mapping file is missing "mapping.orgInfo" export: ${jsAbsPath}`);
|
|
45
|
+
}
|
|
46
|
+
const { orgName, appIdentifier } = mapping.orgInfo;
|
|
47
|
+
if (!orgName) {
|
|
48
|
+
throw new Error(`Mapping file is missing "mapping.orgInfo.orgName": ${jsAbsPath}`);
|
|
49
|
+
}
|
|
50
|
+
if (!appIdentifier) {
|
|
51
|
+
throw new Error(`Mapping file is missing "mapping.orgInfo.appIdentifier": ${jsAbsPath}`);
|
|
52
|
+
}
|
|
53
|
+
const uploadBuffer = fs.readFileSync(jsAbsPath);
|
|
54
|
+
return {
|
|
55
|
+
orgName,
|
|
56
|
+
appIdentifier,
|
|
57
|
+
uploadBuffer,
|
|
58
|
+
uploadFileName: path.basename(jsAbsPath),
|
|
59
|
+
uploadContentType: 'application/javascript',
|
|
60
|
+
configPropertyName: 'transformMapFile',
|
|
61
|
+
filesToCommit: [tsAbsPath, jsAbsPath],
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
class UploadCommand {
|
|
66
|
+
async run(args) {
|
|
67
|
+
await (0, upload_base_1.runUpload)(mappingStrategy, args);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.UploadCommand = UploadCommand;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function buildCommitMessage(userMessage: string, fileId: string): string;
|
|
2
|
+
export interface CommitOptions {
|
|
3
|
+
message?: string;
|
|
4
|
+
branch?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function commitFiles(absPaths: string[], fileId: string, options: CommitOptions): Promise<void>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.commitFiles = exports.buildCommitMessage = void 0;
|
|
27
|
+
const child_process_1 = require("child_process");
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const prompts_1 = require("./prompts");
|
|
30
|
+
function buildCommitMessage(userMessage, fileId) {
|
|
31
|
+
const lines = userMessage.split(/\r?\n/);
|
|
32
|
+
lines[0] = `${lines[0]} [fileId: ${fileId}]`;
|
|
33
|
+
return lines.join('\n');
|
|
34
|
+
}
|
|
35
|
+
exports.buildCommitMessage = buildCommitMessage;
|
|
36
|
+
function runGit(args, cwd) {
|
|
37
|
+
return (0, child_process_1.execFileSync)('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
38
|
+
}
|
|
39
|
+
function tryRunGit(args, cwd) {
|
|
40
|
+
try {
|
|
41
|
+
const stdout = runGit(args, cwd);
|
|
42
|
+
return { ok: true, stdout, stderr: '' };
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
return {
|
|
46
|
+
ok: false,
|
|
47
|
+
stdout: err && err.stdout ? err.stdout.toString() : '',
|
|
48
|
+
stderr: err && err.stderr ? err.stderr.toString() : (err && err.message) || '',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function commitFiles(absPaths, fileId, options) {
|
|
53
|
+
const repoDir = path.dirname(absPaths[0]);
|
|
54
|
+
const relPaths = absPaths.map((p) => path.basename(p));
|
|
55
|
+
const versionCheck = tryRunGit(['--version'], repoDir);
|
|
56
|
+
if (!versionCheck.ok) {
|
|
57
|
+
console.log('git command not available; skipping git commit.');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const insideRepo = tryRunGit(['rev-parse', '--is-inside-work-tree'], repoDir);
|
|
61
|
+
if (!insideRepo.ok || insideRepo.stdout.trim() !== 'true') {
|
|
62
|
+
console.log(`Not inside a git working tree (${repoDir}); skipping git commit.`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const relPath of relPaths) {
|
|
66
|
+
const tracked = tryRunGit(['ls-files', '--error-unmatch', relPath], repoDir);
|
|
67
|
+
if (!tracked.ok) {
|
|
68
|
+
const answer = (await (0, prompts_1.prompt)(`File is not tracked by git: ${relPath}\nAdd it to git? (Y/n): `)).toLowerCase();
|
|
69
|
+
if (answer === 'n' || answer === 'no') {
|
|
70
|
+
console.log('Nothing was done in git.');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (options.branch) {
|
|
76
|
+
const branchResult = tryRunGit(['checkout', '-b', options.branch], repoDir);
|
|
77
|
+
if (!branchResult.ok) {
|
|
78
|
+
throw new Error(`Failed to create branch "${options.branch}": ${branchResult.stderr.trim()}`);
|
|
79
|
+
}
|
|
80
|
+
console.log(`Created and switched to branch "${options.branch}"`);
|
|
81
|
+
}
|
|
82
|
+
let message = options.message;
|
|
83
|
+
if (!message) {
|
|
84
|
+
message = await (0, prompts_1.prompt)('Commit message: ');
|
|
85
|
+
if (!message) {
|
|
86
|
+
throw new Error('A commit message is required');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const finalMessage = buildCommitMessage(message, fileId);
|
|
90
|
+
const addResult = tryRunGit(['add', '--', ...relPaths], repoDir);
|
|
91
|
+
if (!addResult.ok) {
|
|
92
|
+
throw new Error(`git add failed: ${addResult.stderr.trim()}`);
|
|
93
|
+
}
|
|
94
|
+
const commitResult = tryRunGit(['commit', '-m', finalMessage, '--', ...relPaths], repoDir);
|
|
95
|
+
if (!commitResult.ok) {
|
|
96
|
+
throw new Error(`git commit failed: ${commitResult.stderr.trim() || commitResult.stdout.trim()}`);
|
|
97
|
+
}
|
|
98
|
+
console.log(commitResult.stdout.trim());
|
|
99
|
+
}
|
|
100
|
+
exports.commitFiles = commitFiles;
|