@contrail/flexplm 1.3.0 → 1.3.1-alpha.56221f6

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 (149) hide show
  1. package/lib/cli/commands/compile.d.ts +1 -0
  2. package/lib/cli/commands/compile.js +71 -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 +1 -0
  6. package/lib/cli/commands/create.js +75 -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 +10 -0
  10. package/lib/cli/commands/upload.js +219 -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 +2 -0
  14. package/lib/cli/index.js +64 -0
  15. package/lib/cli/index.spec.d.ts +1 -0
  16. package/lib/cli/index.spec.js +79 -0
  17. package/lib/cli/template/mapping-template.ts.template +18 -0
  18. package/lib/entity-processor/base-entity-processor.d.ts +89 -42
  19. package/lib/entity-processor/base-entity-processor.js +438 -385
  20. package/lib/entity-processor/base-entity-processor.spec.d.ts +1 -1
  21. package/lib/entity-processor/base-entity-processor.spec.js +398 -397
  22. package/lib/flexplm-request.d.ts +3 -3
  23. package/lib/flexplm-request.js +34 -34
  24. package/lib/flexplm-utils.d.ts +5 -5
  25. package/lib/flexplm-utils.js +33 -33
  26. package/lib/flexplm-utils.spec.d.ts +1 -1
  27. package/lib/flexplm-utils.spec.js +26 -26
  28. package/lib/index.d.ts +23 -22
  29. package/lib/index.js +39 -38
  30. package/lib/interfaces/interfaces.d.ts +105 -105
  31. package/lib/interfaces/interfaces.js +2 -2
  32. package/lib/interfaces/item-family-changes.d.ts +20 -20
  33. package/lib/interfaces/item-family-changes.js +56 -56
  34. package/lib/interfaces/mapping-file.d.ts +429 -0
  35. package/lib/interfaces/mapping-file.js +2 -0
  36. package/lib/interfaces/publish-change-data.d.ts +19 -19
  37. package/lib/interfaces/publish-change-data.js +32 -32
  38. package/lib/publish/base-process-publish-assortment-callback.d.ts +9 -9
  39. package/lib/publish/base-process-publish-assortment-callback.js +38 -38
  40. package/lib/publish/base-process-publish-assortment.d.ts +118 -93
  41. package/lib/publish/base-process-publish-assortment.js +998 -944
  42. package/lib/publish/base-process-publish-assortment.spec.d.ts +1 -1
  43. package/lib/publish/base-process-publish-assortment.spec.js +1688 -1670
  44. package/lib/publish/mockData.d.ts +1389 -1389
  45. package/lib/publish/mockData.js +4524 -4519
  46. package/lib/transform/identifier-conversion-spec-mockData.js +472 -444
  47. package/lib/transform/identifier-conversion.d.ts +51 -15
  48. package/lib/transform/identifier-conversion.js +248 -212
  49. package/lib/transform/identifier-conversion.spec.d.ts +1 -1
  50. package/lib/transform/identifier-conversion.spec.js +343 -339
  51. package/lib/util/config-defaults.d.ts +8 -8
  52. package/lib/util/config-defaults.js +88 -85
  53. package/lib/util/config-defaults.spec.d.ts +1 -1
  54. package/lib/util/config-defaults.spec.js +302 -293
  55. package/lib/util/data-converter-spec-mockData.js +219 -205
  56. package/lib/util/data-converter.d.ts +136 -39
  57. package/lib/util/data-converter.js +718 -592
  58. package/lib/util/data-converter.spec.d.ts +1 -1
  59. package/lib/util/data-converter.spec.js +906 -904
  60. package/lib/util/error-response-object.d.ts +9 -4
  61. package/lib/util/error-response-object.js +54 -47
  62. package/lib/util/error-response-object.spec.d.ts +1 -1
  63. package/lib/util/error-response-object.spec.js +99 -99
  64. package/lib/util/event-short-message-status.d.ts +19 -19
  65. package/lib/util/event-short-message-status.js +24 -23
  66. package/lib/util/federation.d.ts +15 -15
  67. package/lib/util/federation.js +157 -149
  68. package/lib/util/flexplm-connect.d.ts +29 -22
  69. package/lib/util/flexplm-connect.js +190 -176
  70. package/lib/util/flexplm-connect.spec.d.ts +1 -1
  71. package/lib/util/flexplm-connect.spec.js +88 -88
  72. package/lib/util/logger-config.d.ts +1 -1
  73. package/lib/util/logger-config.js +27 -26
  74. package/lib/util/map-util-spec-mockData.js +219 -205
  75. package/lib/util/map-utils.d.ts +33 -6
  76. package/lib/util/map-utils.js +42 -15
  77. package/lib/util/map-utils.spec.d.ts +1 -1
  78. package/lib/util/map-utils.spec.js +89 -89
  79. package/lib/util/mockData.d.ts +80 -80
  80. package/lib/util/mockData.js +103 -103
  81. package/lib/util/thumbnail-util.d.ts +55 -34
  82. package/lib/util/thumbnail-util.js +242 -215
  83. package/lib/util/thumbnail-util.spec.d.ts +1 -1
  84. package/lib/util/thumbnail-util.spec.js +440 -434
  85. package/lib/util/type-conversion-utils-spec-mockData.js +259 -259
  86. package/lib/util/type-conversion-utils.d.ts +163 -23
  87. package/lib/util/type-conversion-utils.js +408 -265
  88. package/lib/util/type-conversion-utils.spec.d.ts +1 -1
  89. package/lib/util/type-conversion-utils.spec.js +868 -868
  90. package/lib/util/type-defaults.d.ts +74 -16
  91. package/lib/util/type-defaults.js +279 -221
  92. package/lib/util/type-defaults.spec.d.ts +1 -1
  93. package/lib/util/type-defaults.spec.js +516 -516
  94. package/lib/util/type-utils.d.ts +34 -13
  95. package/lib/util/type-utils.js +137 -114
  96. package/lib/util/type-utils.spec.d.ts +1 -1
  97. package/lib/util/type-utils.spec.js +192 -190
  98. package/package.json +21 -6
  99. package/scripts/copy-template.js +10 -0
  100. package/.claude/settings.local.json +0 -8
  101. package/.github/pull_request_template.md +0 -31
  102. package/.github/workflows/flexplm-lib.yml +0 -27
  103. package/.github/workflows/publish-to-npm.yml +0 -124
  104. package/CHANGELOG.md +0 -32
  105. package/publish.bat +0 -5
  106. package/publish.sh +0 -5
  107. package/src/entity-processor/base-entity-processor.spec.ts +0 -460
  108. package/src/entity-processor/base-entity-processor.ts +0 -515
  109. package/src/flexplm-request.ts +0 -28
  110. package/src/flexplm-utils.spec.ts +0 -27
  111. package/src/flexplm-utils.ts +0 -29
  112. package/src/index.ts +0 -22
  113. package/src/interfaces/interfaces.ts +0 -122
  114. package/src/interfaces/item-family-changes.ts +0 -67
  115. package/src/interfaces/publish-change-data.ts +0 -43
  116. package/src/publish/base-process-publish-assortment-callback.ts +0 -50
  117. package/src/publish/base-process-publish-assortment.spec.ts +0 -1992
  118. package/src/publish/base-process-publish-assortment.ts +0 -1134
  119. package/src/publish/mockData.ts +0 -4561
  120. package/src/transform/identifier-conversion-spec-mockData.ts +0 -496
  121. package/src/transform/identifier-conversion.spec.ts +0 -354
  122. package/src/transform/identifier-conversion.ts +0 -282
  123. package/src/util/config-defaults.spec.ts +0 -350
  124. package/src/util/config-defaults.ts +0 -93
  125. package/src/util/data-converter-spec-mockData.ts +0 -231
  126. package/src/util/data-converter.spec.ts +0 -1041
  127. package/src/util/data-converter.ts +0 -762
  128. package/src/util/error-response-object.spec.ts +0 -116
  129. package/src/util/error-response-object.ts +0 -50
  130. package/src/util/event-short-message-status.ts +0 -22
  131. package/src/util/federation.ts +0 -172
  132. package/src/util/flexplm-connect.spec.ts +0 -132
  133. package/src/util/flexplm-connect.ts +0 -208
  134. package/src/util/logger-config.ts +0 -20
  135. package/src/util/map-util-spec-mockData.ts +0 -231
  136. package/src/util/map-utils.spec.ts +0 -103
  137. package/src/util/map-utils.ts +0 -41
  138. package/src/util/mockData.ts +0 -101
  139. package/src/util/thumbnail-util.spec.ts +0 -508
  140. package/src/util/thumbnail-util.ts +0 -272
  141. package/src/util/type-conversion-utils-spec-mockData.ts +0 -271
  142. package/src/util/type-conversion-utils.spec.ts +0 -968
  143. package/src/util/type-conversion-utils.ts +0 -460
  144. package/src/util/type-defaults.spec.ts +0 -669
  145. package/src/util/type-defaults.ts +0 -281
  146. package/src/util/type-utils.spec.ts +0 -227
  147. package/src/util/type-utils.ts +0 -144
  148. package/tsconfig.json +0 -29
  149. package/tslint.json +0 -57
@@ -0,0 +1 @@
1
+ export declare function runCompile(tsPath: string): Promise<void>;
@@ -0,0 +1,71 @@
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.runCompile = void 0;
27
+ const fs = __importStar(require("fs"));
28
+ const path = __importStar(require("path"));
29
+ function loadTypescript() {
30
+ try {
31
+ return require('typescript');
32
+ }
33
+ catch (e) {
34
+ throw new Error('compile requires the "typescript" package. Install it in your project: npm install --save-dev typescript');
35
+ }
36
+ }
37
+ async function runCompile(tsPath) {
38
+ const absPath = path.resolve(process.cwd(), tsPath);
39
+ if (!fs.existsSync(absPath)) {
40
+ throw new Error(`File not found: ${absPath}`);
41
+ }
42
+ if (!absPath.endsWith('.ts')) {
43
+ throw new Error(`Expected a .ts file, got: ${absPath}`);
44
+ }
45
+ const ts = loadTypescript();
46
+ const source = fs.readFileSync(absPath, 'utf8');
47
+ const result = ts.transpileModule(source, {
48
+ fileName: path.basename(absPath),
49
+ compilerOptions: {
50
+ module: ts.ModuleKind.CommonJS,
51
+ target: ts.ScriptTarget.ES2020,
52
+ esModuleInterop: true,
53
+ },
54
+ reportDiagnostics: true,
55
+ });
56
+ const diagnostics = result.diagnostics || [];
57
+ if (diagnostics.length > 0) {
58
+ const formatHost = {
59
+ getCanonicalFileName: (f) => f,
60
+ getCurrentDirectory: () => process.cwd(),
61
+ getNewLine: () => '\n',
62
+ };
63
+ const formatted = ts.formatDiagnosticsWithColorAndContext(diagnostics, formatHost);
64
+ process.stderr.write(formatted);
65
+ throw new Error(`Compile failed: ${diagnostics.length} diagnostic(s)`);
66
+ }
67
+ const outPath = absPath.replace(/\.ts$/, '.js');
68
+ fs.writeFileSync(outPath, result.outputText, 'utf8');
69
+ console.log(`Compiled ${outPath}`);
70
+ }
71
+ exports.runCompile = runCompile;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
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
+ const compile_1 = require("./compile");
30
+ describe('runCompile', () => {
31
+ let tempDir;
32
+ let originalCwd;
33
+ let logSpy;
34
+ let stderrSpy;
35
+ beforeEach(() => {
36
+ originalCwd = process.cwd();
37
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'flexplm-compile-'));
38
+ process.chdir(tempDir);
39
+ logSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
40
+ stderrSpy = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
41
+ });
42
+ afterEach(() => {
43
+ logSpy.mockRestore();
44
+ stderrSpy.mockRestore();
45
+ process.chdir(originalCwd);
46
+ fs.rmSync(tempDir, { recursive: true, force: true });
47
+ });
48
+ it('transpiles a .ts file to a sibling .js file', async () => {
49
+ const tsPath = path.join(tempDir, 'mapping.ts');
50
+ fs.writeFileSync(tsPath, `export const mapping = { orgName: 'acme' };\n`, 'utf8');
51
+ await (0, compile_1.runCompile)('mapping.ts');
52
+ const jsPath = path.join(tempDir, 'mapping.js');
53
+ expect(fs.existsSync(jsPath)).toBe(true);
54
+ const js = fs.readFileSync(jsPath, 'utf8');
55
+ expect(js).toContain('exports.mapping');
56
+ expect(js).toContain("orgName: 'acme'");
57
+ });
58
+ it('resolves the input path relative to cwd', async () => {
59
+ const subdir = path.join(tempDir, 'nested');
60
+ fs.mkdirSync(subdir);
61
+ const tsPath = path.join(subdir, 'm.ts');
62
+ fs.writeFileSync(tsPath, 'export const x = 1;\n', 'utf8');
63
+ await (0, compile_1.runCompile)('nested/m.ts');
64
+ expect(fs.existsSync(path.join(subdir, 'm.js'))).toBe(true);
65
+ });
66
+ it('throws when the input file does not exist', async () => {
67
+ await expect((0, compile_1.runCompile)('nope.ts')).rejects.toThrow(/File not found/);
68
+ });
69
+ it('throws when the input is not a .ts file', async () => {
70
+ const jsPath = path.join(tempDir, 'mapping.js');
71
+ fs.writeFileSync(jsPath, 'module.exports = {};', 'utf8');
72
+ await expect((0, compile_1.runCompile)('mapping.js')).rejects.toThrow(/Expected a \.ts file/);
73
+ });
74
+ it('throws on a TypeScript syntax error', async () => {
75
+ const tsPath = path.join(tempDir, 'broken.ts');
76
+ fs.writeFileSync(tsPath, 'export const = ;\n', 'utf8');
77
+ await expect((0, compile_1.runCompile)('broken.ts')).rejects.toThrow(/Compile failed/);
78
+ expect(fs.existsSync(path.join(tempDir, 'broken.js'))).toBe(false);
79
+ });
80
+ });
@@ -0,0 +1 @@
1
+ export declare function runCreate(): Promise<void>;
@@ -0,0 +1,75 @@
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.runCreate = void 0;
27
+ const fs = __importStar(require("fs"));
28
+ const path = __importStar(require("path"));
29
+ const readline = __importStar(require("readline"));
30
+ const TEMPLATE_FILENAME = 'mapping-template.ts.template';
31
+ const PLACEHOLDER = '<ORG_NAME>';
32
+ function prompt(question) {
33
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
34
+ const onSigint = () => {
35
+ rl.close();
36
+ process.stdout.write('\n');
37
+ process.exit(130);
38
+ };
39
+ process.once('SIGINT', onSigint);
40
+ return new Promise((resolve) => {
41
+ rl.question(question, (answer) => {
42
+ process.removeListener('SIGINT', onSigint);
43
+ rl.close();
44
+ resolve(answer);
45
+ });
46
+ });
47
+ }
48
+ function findTemplate() {
49
+ const candidates = [
50
+ path.join(__dirname, '..', 'template', TEMPLATE_FILENAME),
51
+ path.join(__dirname, '..', '..', '..', 'src', 'cli', 'template', TEMPLATE_FILENAME),
52
+ ];
53
+ for (const candidate of candidates) {
54
+ if (fs.existsSync(candidate)) {
55
+ return candidate;
56
+ }
57
+ }
58
+ throw new Error(`Could not locate ${TEMPLATE_FILENAME}. Tried:\n ${candidates.join('\n ')}`);
59
+ }
60
+ async function runCreate() {
61
+ const orgName = (await prompt('orgName: ')).trim();
62
+ if (!orgName) {
63
+ throw new Error('orgName is required');
64
+ }
65
+ const templatePath = findTemplate();
66
+ const templateBody = fs.readFileSync(templatePath, 'utf8');
67
+ const rendered = templateBody.split(PLACEHOLDER).join(orgName);
68
+ const outPath = path.resolve(process.cwd(), `${orgName}-transformMapping.ts`);
69
+ if (fs.existsSync(outPath)) {
70
+ throw new Error(`Refusing to overwrite existing file: ${outPath}`);
71
+ }
72
+ fs.writeFileSync(outPath, rendered, 'utf8');
73
+ console.log(`Created ${outPath}`);
74
+ }
75
+ exports.runCreate = runCreate;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,78 @@
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', () => {
38
+ let tempDir;
39
+ let originalCwd;
40
+ let logSpy;
41
+ beforeEach(() => {
42
+ originalCwd = process.cwd();
43
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'flexplm-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>-transformMapping.ts with the placeholder replaced', async () => {
54
+ nextAnswer = 'acme';
55
+ await (0, create_1.runCreate)();
56
+ const outPath = path.join(tempDir, 'acme-transformMapping.ts');
57
+ expect(fs.existsSync(outPath)).toBe(true);
58
+ const contents = fs.readFileSync(outPath, 'utf8');
59
+ expect(contents).toContain("orgName: 'acme'");
60
+ expect(contents).not.toContain('<ORG_NAME>');
61
+ });
62
+ it('trims whitespace around the orgName input', async () => {
63
+ nextAnswer = ' acme ';
64
+ await (0, create_1.runCreate)();
65
+ expect(fs.existsSync(path.join(tempDir, 'acme-transformMapping.ts'))).toBe(true);
66
+ });
67
+ it('throws when orgName is empty', async () => {
68
+ nextAnswer = ' ';
69
+ await expect((0, create_1.runCreate)()).rejects.toThrow(/orgName is required/);
70
+ });
71
+ it('refuses to overwrite an existing file', async () => {
72
+ const existing = path.join(tempDir, 'acme-transformMapping.ts');
73
+ fs.writeFileSync(existing, 'do not clobber', 'utf8');
74
+ nextAnswer = 'acme';
75
+ await expect((0, create_1.runCreate)()).rejects.toThrow(/Refusing to overwrite/);
76
+ expect(fs.readFileSync(existing, 'utf8')).toEqual('do not clobber');
77
+ });
78
+ });
@@ -0,0 +1,10 @@
1
+ interface UploadOptions {
2
+ filePath: string;
3
+ message?: string;
4
+ branch?: string;
5
+ skipGit: boolean;
6
+ }
7
+ export declare function parseUploadArgs(args: string[]): UploadOptions;
8
+ export declare function buildCommitMessage(userMessage: string, fileId: string): string;
9
+ export declare function runUpload(args: string[]): Promise<void>;
10
+ export {};
@@ -0,0 +1,219 @@
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.runUpload = exports.buildCommitMessage = exports.parseUploadArgs = void 0;
27
+ const child_process_1 = require("child_process");
28
+ const fs = __importStar(require("fs"));
29
+ const path = __importStar(require("path"));
30
+ const readline = __importStar(require("readline"));
31
+ const sdk_1 = require("@contrail/sdk");
32
+ function prompt(question) {
33
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
34
+ return new Promise((resolve) => {
35
+ rl.question(question, (answer) => {
36
+ rl.close();
37
+ resolve(answer.trim());
38
+ });
39
+ });
40
+ }
41
+ function promptHidden(question) {
42
+ return new Promise((resolve) => {
43
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
44
+ const rlAny = rl;
45
+ rlAny._writeToOutput = (str) => {
46
+ if (str.includes(question)) {
47
+ rlAny.output.write(str);
48
+ }
49
+ };
50
+ rl.question(question, (answer) => {
51
+ rl.close();
52
+ process.stdout.write('\n');
53
+ resolve(answer);
54
+ });
55
+ });
56
+ }
57
+ function parseUploadArgs(args) {
58
+ let filePath;
59
+ let message;
60
+ let branch;
61
+ let skipGit = false;
62
+ for (let i = 0; i < args.length; i++) {
63
+ const a = args[i];
64
+ if (a === '-m') {
65
+ message = args[++i];
66
+ if (message === undefined) {
67
+ throw new Error('-m requires a commit message argument');
68
+ }
69
+ }
70
+ else if (a === '-b') {
71
+ branch = args[++i];
72
+ if (branch === undefined) {
73
+ throw new Error('-b requires a branch name argument');
74
+ }
75
+ }
76
+ else if (a === '--skip-git' || a === '--skipGit') {
77
+ skipGit = true;
78
+ }
79
+ else if (a.startsWith('-')) {
80
+ throw new Error(`Unknown option: ${a}`);
81
+ }
82
+ else if (!filePath) {
83
+ filePath = a;
84
+ }
85
+ else {
86
+ throw new Error(`Unexpected argument: ${a}`);
87
+ }
88
+ }
89
+ if (!filePath) {
90
+ throw new Error('upload: missing <path.js> argument');
91
+ }
92
+ return { filePath, message, branch, skipGit };
93
+ }
94
+ exports.parseUploadArgs = parseUploadArgs;
95
+ function runGit(args, cwd) {
96
+ return (0, child_process_1.execFileSync)('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
97
+ }
98
+ function tryRunGit(args, cwd) {
99
+ try {
100
+ const stdout = runGit(args, cwd);
101
+ return { ok: true, stdout, stderr: '' };
102
+ }
103
+ catch (err) {
104
+ return {
105
+ ok: false,
106
+ stdout: err && err.stdout ? err.stdout.toString() : '',
107
+ stderr: err && err.stderr ? err.stderr.toString() : (err && err.message) || '',
108
+ };
109
+ }
110
+ }
111
+ function buildCommitMessage(userMessage, fileId) {
112
+ const lines = userMessage.split(/\r?\n/);
113
+ lines[0] = `${lines[0]} [fileId: ${fileId}]`;
114
+ return lines.join('\n');
115
+ }
116
+ exports.buildCommitMessage = buildCommitMessage;
117
+ async function commitToGit(absPath, fileId, options) {
118
+ const repoDir = path.dirname(absPath);
119
+ const versionCheck = tryRunGit(['--version'], repoDir);
120
+ if (!versionCheck.ok) {
121
+ console.log('git command not available; skipping git commit.');
122
+ return;
123
+ }
124
+ const insideRepo = tryRunGit(['rev-parse', '--is-inside-work-tree'], repoDir);
125
+ if (!insideRepo.ok || insideRepo.stdout.trim() !== 'true') {
126
+ console.log(`Not inside a git working tree (${repoDir}); skipping git commit.`);
127
+ return;
128
+ }
129
+ const tracked = tryRunGit(['ls-files', '--error-unmatch', absPath], repoDir);
130
+ if (!tracked.ok) {
131
+ const answer = (await prompt(`File is not tracked by git: ${absPath}\nAdd it to git? (y/N): `)).toLowerCase();
132
+ if (answer !== 'y' && answer !== 'yes') {
133
+ console.log('Nothing was done in git.');
134
+ return;
135
+ }
136
+ }
137
+ if (options.branch) {
138
+ const branchResult = tryRunGit(['checkout', '-b', options.branch], repoDir);
139
+ if (!branchResult.ok) {
140
+ throw new Error(`Failed to create branch "${options.branch}": ${branchResult.stderr.trim()}`);
141
+ }
142
+ console.log(`Created and switched to branch "${options.branch}"`);
143
+ }
144
+ let message = options.message;
145
+ if (!message) {
146
+ message = await prompt('Commit message: ');
147
+ if (!message) {
148
+ throw new Error('A commit message is required');
149
+ }
150
+ }
151
+ const finalMessage = buildCommitMessage(message, fileId);
152
+ const addResult = tryRunGit(['add', '--', absPath], repoDir);
153
+ if (!addResult.ok) {
154
+ throw new Error(`git add failed: ${addResult.stderr.trim()}`);
155
+ }
156
+ const commitResult = tryRunGit(['commit', '-m', finalMessage, '--', absPath], repoDir);
157
+ if (!commitResult.ok) {
158
+ throw new Error(`git commit failed: ${commitResult.stderr.trim() || commitResult.stdout.trim()}`);
159
+ }
160
+ console.log(commitResult.stdout.trim());
161
+ }
162
+ async function runUpload(args) {
163
+ const options = parseUploadArgs(args);
164
+ const absPath = path.resolve(process.cwd(), options.filePath);
165
+ if (!fs.existsSync(absPath)) {
166
+ throw new Error(`File not found: ${absPath}`);
167
+ }
168
+ if (!absPath.endsWith('.js')) {
169
+ throw new Error(`Expected a .js file, got: ${absPath}`);
170
+ }
171
+ let email = process.env.CONTRAIL_CLI_EMAIL;
172
+ let password = process.env.CONTRAIL_CLI_PASSWORD;
173
+ if (!email) {
174
+ email = await prompt('Email: ');
175
+ }
176
+ if (!password) {
177
+ password = await promptHidden('Password: ');
178
+ }
179
+ if (!email || !password) {
180
+ throw new Error('Email and password are required');
181
+ }
182
+ delete require.cache[absPath];
183
+ const loaded = require(absPath);
184
+ const mapping = loaded && loaded.mapping;
185
+ if (!mapping || !mapping.orgInfo) {
186
+ throw new Error(`Mapping file is missing "mapping.orgInfo" export: ${absPath}`);
187
+ }
188
+ const { orgName, appIdentifier } = mapping.orgInfo;
189
+ if (!orgName) {
190
+ throw new Error(`Mapping file is missing "mapping.orgInfo.orgName": ${absPath}`);
191
+ }
192
+ if (!appIdentifier) {
193
+ throw new Error(`Mapping file is missing "mapping.orgInfo.appIdentifier": ${absPath}`);
194
+ }
195
+ await (0, sdk_1.login)({ orgSlug: orgName, email, password });
196
+ console.log(`Logged in to org "${orgName}" as ${email}`);
197
+ const apps = await new sdk_1.Entities().get({
198
+ entityName: 'app',
199
+ criteria: { identifier: appIdentifier },
200
+ });
201
+ if (!apps || apps.length !== 1) {
202
+ throw new Error(`Expected exactly one app with identifier "${appIdentifier}" in org "${orgName}", found ${apps ? apps.length : 0}`);
203
+ }
204
+ const app = apps[0];
205
+ const buffer = fs.readFileSync(absPath);
206
+ const fileName = path.basename(absPath);
207
+ const fileOwner = `app:${app.id}`;
208
+ const uploadedFile = await new sdk_1.Files().createAndUploadFileFromBuffer(buffer, 'application/javascript', fileName, fileOwner);
209
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
210
+ const responsePath = `${absPath}.uploaded-${timestamp}.json`;
211
+ fs.writeFileSync(responsePath, JSON.stringify(uploadedFile, null, 2), 'utf8');
212
+ console.log(`Wrote response to ${responsePath}`);
213
+ console.log(`FILE ID: ${uploadedFile.id}`);
214
+ if (options.skipGit) {
215
+ return;
216
+ }
217
+ await commitToGit(absPath, uploadedFile.id, options);
218
+ }
219
+ exports.runUpload = runUpload;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
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('parseUploadArgs', () => {
10
+ it('parses a bare file path', () => {
11
+ const opts = (0, upload_1.parseUploadArgs)(['mapping.js']);
12
+ expect(opts).toEqual({
13
+ filePath: 'mapping.js',
14
+ message: undefined,
15
+ branch: undefined,
16
+ skipGit: false,
17
+ });
18
+ });
19
+ it('parses -m commit message option', () => {
20
+ const opts = (0, upload_1.parseUploadArgs)(['mapping.js', '-m', 'my message']);
21
+ expect(opts.message).toEqual('my message');
22
+ expect(opts.skipGit).toBe(false);
23
+ });
24
+ it('parses -b branch option', () => {
25
+ const opts = (0, upload_1.parseUploadArgs)(['mapping.js', '-b', 'feature/x']);
26
+ expect(opts.branch).toEqual('feature/x');
27
+ });
28
+ it('parses --skip-git flag', () => {
29
+ const opts = (0, upload_1.parseUploadArgs)(['mapping.js', '--skip-git']);
30
+ expect(opts.skipGit).toBe(true);
31
+ });
32
+ it('accepts the legacy --skipGit alias', () => {
33
+ const opts = (0, upload_1.parseUploadArgs)(['mapping.js', '--skipGit']);
34
+ expect(opts.skipGit).toBe(true);
35
+ });
36
+ it('parses options before the file path', () => {
37
+ const opts = (0, upload_1.parseUploadArgs)(['-m', 'msg', '-b', 'br', 'mapping.js']);
38
+ expect(opts).toEqual({
39
+ filePath: 'mapping.js',
40
+ message: 'msg',
41
+ branch: 'br',
42
+ skipGit: false,
43
+ });
44
+ });
45
+ it('parses all options together', () => {
46
+ const opts = (0, upload_1.parseUploadArgs)(['mapping.js', '-m', 'msg', '-b', 'br', '--skip-git']);
47
+ expect(opts).toEqual({
48
+ filePath: 'mapping.js',
49
+ message: 'msg',
50
+ branch: 'br',
51
+ skipGit: true,
52
+ });
53
+ });
54
+ it('throws when -m is missing its value', () => {
55
+ expect(() => (0, upload_1.parseUploadArgs)(['mapping.js', '-m'])).toThrow(/-m requires a commit message/);
56
+ });
57
+ it('throws when -b is missing its value', () => {
58
+ expect(() => (0, upload_1.parseUploadArgs)(['mapping.js', '-b'])).toThrow(/-b requires a branch name/);
59
+ });
60
+ it('throws on unknown option', () => {
61
+ expect(() => (0, upload_1.parseUploadArgs)(['mapping.js', '--bogus'])).toThrow(/Unknown option: --bogus/);
62
+ });
63
+ it('throws when an extra positional argument is supplied', () => {
64
+ expect(() => (0, upload_1.parseUploadArgs)(['mapping.js', 'extra.js'])).toThrow(/Unexpected argument: extra\.js/);
65
+ });
66
+ it('throws when no file path is provided', () => {
67
+ expect(() => (0, upload_1.parseUploadArgs)([])).toThrow(/missing <path\.js>/);
68
+ });
69
+ it('throws when only options are provided', () => {
70
+ expect(() => (0, upload_1.parseUploadArgs)(['--skip-git'])).toThrow(/missing <path\.js>/);
71
+ });
72
+ });
73
+ describe('buildCommitMessage', () => {
74
+ it('appends fileId to the first line of a single-line message', () => {
75
+ expect((0, upload_1.buildCommitMessage)('initial commit', 'abc123')).toEqual('initial commit [fileId: abc123]');
76
+ });
77
+ it('only appends fileId to the first line of a multi-line message', () => {
78
+ const result = (0, upload_1.buildCommitMessage)('header line\nbody line 1\nbody line 2', 'xyz');
79
+ expect(result).toEqual('header line [fileId: xyz]\nbody line 1\nbody line 2');
80
+ });
81
+ it('handles CRLF line endings', () => {
82
+ const result = (0, upload_1.buildCommitMessage)('header\r\nbody', 'fid');
83
+ expect(result).toEqual('header [fileId: fid]\nbody');
84
+ });
85
+ it('handles an empty message', () => {
86
+ expect((0, upload_1.buildCommitMessage)('', 'fid')).toEqual(' [fileId: fid]');
87
+ });
88
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(): Promise<void>;