@thinkwise/testwise 0.2.0-beta.3 → 0.2.5

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 (136) hide show
  1. package/Testwise.ts +8 -7
  2. package/artifact-builder/ArtifactManager.ts +0 -1
  3. package/artifact-builder/InterfaceGenerator.ts +73 -83
  4. package/artifact-builder/ModelDataBuilder.ts +74 -86
  5. package/artifact-builder/ModelDataRefiner.ts +18 -13
  6. package/artifact-builder/SchemaGenerator.ts +1 -4
  7. package/artifact-builder/ScreenInterfaceRefiner.ts +0 -5
  8. package/artifact-builder/SelectorBuilder.ts +8 -1
  9. package/artifact-builder/SubjectComponentGenerator.ts +77 -7
  10. package/artifact-builder/SubjectGenerator.ts +3 -3
  11. package/artifact-builder/SubjectRegistration.ts +69 -61
  12. package/artifact-builder/helpers/DataRetriever.ts +6 -3
  13. package/artifact-builder/helpers/NamingHandler.ts +28 -20
  14. package/artifact-builder/helpers/Stopwatch.ts +13 -0
  15. package/artifact-builder/helpers/index.ts +1 -0
  16. package/components/BaseComponentObjects.ts +4 -1
  17. package/components/action-bar/ActionBar.ts +3 -3
  18. package/components/grid/Grid.ts +18 -21
  19. package/components/tab/BaseTab.ts +2 -2
  20. package/components/tab/BaseTabObjects.ts +1 -1
  21. package/components/tab/DetailTabPage.ts +2 -2
  22. package/components/tab/Tab.ts +4 -4
  23. package/controls/LookupDropdown.ts +7 -2
  24. package/dist/Testwise.d.ts +1 -0
  25. package/dist/Testwise.js +15 -6
  26. package/dist/Testwise.js.map +1 -1
  27. package/dist/artifact-builder/ArtifactManager.js.map +1 -1
  28. package/dist/artifact-builder/InterfaceGenerator.d.ts +1 -1
  29. package/dist/artifact-builder/InterfaceGenerator.js +60 -67
  30. package/dist/artifact-builder/InterfaceGenerator.js.map +1 -1
  31. package/dist/artifact-builder/ModelDataBuilder.js +49 -60
  32. package/dist/artifact-builder/ModelDataBuilder.js.map +1 -1
  33. package/dist/artifact-builder/ModelDataRefiner.js +11 -7
  34. package/dist/artifact-builder/ModelDataRefiner.js.map +1 -1
  35. package/dist/artifact-builder/SchemaGenerator.js +0 -2
  36. package/dist/artifact-builder/SchemaGenerator.js.map +1 -1
  37. package/dist/artifact-builder/ScreenInterfaceRefiner.js +0 -5
  38. package/dist/artifact-builder/ScreenInterfaceRefiner.js.map +1 -1
  39. package/dist/artifact-builder/SelectorBuilder.js +3 -1
  40. package/dist/artifact-builder/SelectorBuilder.js.map +1 -1
  41. package/dist/artifact-builder/SubjectComponentGenerator.d.ts +4 -0
  42. package/dist/artifact-builder/SubjectComponentGenerator.js +61 -5
  43. package/dist/artifact-builder/SubjectComponentGenerator.js.map +1 -1
  44. package/dist/artifact-builder/SubjectGenerator.js +1 -1
  45. package/dist/artifact-builder/SubjectGenerator.js.map +1 -1
  46. package/dist/artifact-builder/SubjectRegistration.d.ts +10 -11
  47. package/dist/artifact-builder/SubjectRegistration.js +52 -44
  48. package/dist/artifact-builder/SubjectRegistration.js.map +1 -1
  49. package/dist/artifact-builder/helpers/DataRetriever.js +4 -3
  50. package/dist/artifact-builder/helpers/DataRetriever.js.map +1 -1
  51. package/dist/artifact-builder/helpers/NamingHandler.d.ts +2 -1
  52. package/dist/artifact-builder/helpers/NamingHandler.js +23 -16
  53. package/dist/artifact-builder/helpers/NamingHandler.js.map +1 -1
  54. package/dist/artifact-builder/helpers/Stopwatch.d.ts +5 -0
  55. package/dist/artifact-builder/helpers/Stopwatch.js +13 -0
  56. package/dist/artifact-builder/helpers/Stopwatch.js.map +1 -0
  57. package/dist/artifact-builder/helpers/index.d.ts +1 -0
  58. package/dist/artifact-builder/helpers/index.js +1 -0
  59. package/dist/artifact-builder/helpers/index.js.map +1 -1
  60. package/dist/components/BaseComponentObjects.d.ts +1 -0
  61. package/dist/components/BaseComponentObjects.js +3 -1
  62. package/dist/components/BaseComponentObjects.js.map +1 -1
  63. package/dist/components/action-bar/ActionBar.d.ts +1 -1
  64. package/dist/components/action-bar/ActionBar.js +3 -3
  65. package/dist/components/grid/Grid.d.ts +1 -0
  66. package/dist/components/grid/Grid.js +4 -1
  67. package/dist/components/grid/Grid.js.map +1 -1
  68. package/dist/components/tab/BaseTab.d.ts +2 -2
  69. package/dist/components/tab/BaseTab.js +2 -2
  70. package/dist/components/tab/BaseTab.js.map +1 -1
  71. package/dist/components/tab/BaseTabObjects.js +1 -1
  72. package/dist/components/tab/BaseTabObjects.js.map +1 -1
  73. package/dist/components/tab/DetailTabPage.d.ts +2 -2
  74. package/dist/components/tab/DetailTabPage.js +2 -2
  75. package/dist/components/tab/DetailTabPage.js.map +1 -1
  76. package/dist/components/tab/Tab.d.ts +3 -3
  77. package/dist/components/tab/Tab.js +4 -4
  78. package/dist/components/tab/Tab.js.map +1 -1
  79. package/dist/controls/LookupDropdown.d.ts +3 -7
  80. package/dist/controls/LookupDropdown.js.map +1 -1
  81. package/dist/enums/ElementTypes.d.ts +1 -1
  82. package/dist/enums/ElementTypes.js +1 -1
  83. package/dist/enums/ElementTypes.js.map +1 -1
  84. package/dist/helpers/ConfigChecker.d.ts +3 -0
  85. package/dist/helpers/ConfigChecker.js +7 -0
  86. package/dist/helpers/ConfigChecker.js.map +1 -0
  87. package/dist/helpers/LoginHelper.js +1 -1
  88. package/dist/helpers/LoginHelper.js.map +1 -1
  89. package/dist/interfaces/IComponentObjects.d.ts +1 -0
  90. package/dist/page-extensions/SubjectRegistry.d.ts +0 -8
  91. package/dist/page-extensions/SubjectRegistry.js +2 -6
  92. package/dist/page-extensions/SubjectRegistry.js.map +1 -1
  93. package/dist/page-extensions/index.d.ts +0 -1
  94. package/dist/page-extensions/index.js +0 -1
  95. package/dist/page-extensions/index.js.map +1 -1
  96. package/dist/services/IndiciumApi.service.d.ts +27 -0
  97. package/dist/services/IndiciumApi.service.js +135 -0
  98. package/dist/services/IndiciumApi.service.js.map +1 -0
  99. package/dist/templates/test-artifacts/SubjectPageBase.d.ts +5 -0
  100. package/dist/templates/test-artifacts/SubjectPageBase.js +6 -0
  101. package/dist/templates/test-artifacts/SubjectPageBase.js.map +1 -0
  102. package/dist/templates/test-artifacts/screens/index.d.ts +1 -0
  103. package/dist/templates/test-artifacts/screens/index.js +2 -0
  104. package/dist/templates/test-artifacts/screens/index.js.map +1 -0
  105. package/dist/templates/test-artifacts/subjects/index.d.ts +1 -0
  106. package/dist/templates/test-artifacts/subjects/index.js +2 -0
  107. package/dist/templates/test-artifacts/subjects/index.js.map +1 -0
  108. package/enums/ElementTypes.ts +2 -2
  109. package/helpers/ConfigChecker.ts +7 -0
  110. package/helpers/LoginHelper.ts +1 -1
  111. package/interfaces/IComponentObjects.ts +1 -0
  112. package/interfaces/IRegisteredSubjects.ts +1 -1
  113. package/package.json +5 -3
  114. package/page-extensions/SubjectRegistry.ts +2 -19
  115. package/page-extensions/index.ts +0 -1
  116. package/scripts/main.js +63 -82
  117. package/scripts/postinstall.js +40 -42
  118. package/scripts/setup.js +37 -37
  119. package/scripts/sync.js +726 -39
  120. package/services/ConfigBuilder.ts +1 -1
  121. package/services/IndiciumApi.service.ts +159 -0
  122. package/templates/SubjectRegistry.template.ts +73 -0
  123. package/templates/test-artifacts/SubjectPageBase.ts +9 -0
  124. package/templates/test-artifacts/screens/index.ts +0 -0
  125. package/templates/test-artifacts/subjects/index.ts +0 -0
  126. package/tsconfig.json +2 -3
  127. package/types/Components.ts +1 -1
  128. package/dist/config.json +0 -10
  129. package/dist/page-extensions/SubjectProvider.d.ts +0 -11
  130. package/dist/page-extensions/SubjectProvider.js +0 -24
  131. package/dist/page-extensions/SubjectProvider.js.map +0 -1
  132. package/dist/test-artifacts/index.d.ts +0 -3
  133. package/dist/test-artifacts/index.js +0 -4
  134. package/dist/test-artifacts/index.js.map +0 -1
  135. package/page-extensions/SubjectProvider.ts +0 -41
  136. package/test-artifacts/index.ts +0 -3
@@ -0,0 +1,135 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /** biome-ignore-all lint/style/noNonNullAssertion: because null is bad */
3
+ /** biome-ignore-all lint/suspicious/noExplicitAny: because it is necessary */
4
+ import axios from 'axios';
5
+ import { testwiseConfig } from './ConfigBuilder.js';
6
+ export class IndiciumApiService {
7
+ constructor() {
8
+ this.axiosInstance = null;
9
+ this.metaEndpoint = null;
10
+ this.guiApplId = null;
11
+ this.isVerified = false;
12
+ this.initPromise = this.initialize();
13
+ }
14
+ /**
15
+ * Internal helper to ensure the service is fully initialized and verified
16
+ * before any API calls are made.
17
+ */
18
+ async ensureReady() {
19
+ await this.initPromise;
20
+ }
21
+ async initialize() {
22
+ const config = testwiseConfig();
23
+ const serviceUrl = config.get('environmentSettings.serviceUrl')?.replace(/\/$/, '');
24
+ const metaEndpoint = config.get('environmentSettings.metaEndpoint')?.replace(/^\//, '').replace(/\/$/, '');
25
+ const authUser = config.get('environmentSettings.authUser');
26
+ const authUserPassword = config.get('environmentSettings.authUserPassword');
27
+ const guiApplAlias = config.get('environmentSettings.guiApplAlias');
28
+ if (!serviceUrl || !metaEndpoint || !authUser || !authUserPassword || !guiApplAlias) {
29
+ console.warn('IndiciumApiService: Configuration is incomplete.');
30
+ return;
31
+ }
32
+ this.metaEndpoint = metaEndpoint;
33
+ this.axiosInstance = axios.create({
34
+ baseURL: serviceUrl,
35
+ headers: {
36
+ Authorization: `Basic ${Buffer.from(`${authUser}:${authUserPassword}`).toString('base64')}`,
37
+ accept: '*/*'
38
+ }
39
+ });
40
+ await this.verifyConnection(guiApplAlias);
41
+ }
42
+ async verifyConnection(targetAlias) {
43
+ if (!this.axiosInstance || !this.metaEndpoint)
44
+ return;
45
+ try {
46
+ const response = await this.axiosInstance.get(`/iam/${this.metaEndpoint}/i_ui_gui_appl`);
47
+ const apps = response.data?.value || [];
48
+ const foundApp = apps.find((app) => app.gui_appl_alias?.toString().toLowerCase() === targetAlias.toString().toLowerCase());
49
+ if (foundApp) {
50
+ this.guiApplId = foundApp.gui_appl_id;
51
+ this.isVerified = true;
52
+ }
53
+ else {
54
+ console.warn(`IndiciumApiService: No GUI Application found for alias: ${targetAlias}`);
55
+ }
56
+ }
57
+ catch (error) {
58
+ console.error('IndiciumApiService: Verification failed:', error);
59
+ }
60
+ }
61
+ async canConnectToProject() {
62
+ await this.ensureReady();
63
+ return this.isVerified;
64
+ }
65
+ async getVerifiedGuiApplId() {
66
+ await this.ensureReady();
67
+ return this.guiApplId;
68
+ }
69
+ async getAllTables() {
70
+ await this.ensureReady();
71
+ if (!this.isVerified || !this.guiApplId)
72
+ return [];
73
+ try {
74
+ const response = await this.axiosInstance.get(`/iam/${this.metaEndpoint}/i_ui_tab?$filter=gui_appl_id%20eq%20${this.guiApplId}`);
75
+ return response.data?.value || [];
76
+ }
77
+ catch (error) {
78
+ console.error('Failed to fetch tables:', error);
79
+ return [];
80
+ }
81
+ }
82
+ async getAllColumns() {
83
+ await this.ensureReady();
84
+ if (!this.isVerified || !this.guiApplId)
85
+ return [];
86
+ try {
87
+ const response = await this.axiosInstance.get(`/iam/${this.metaEndpoint}/i_ui_col?$filter=gui_appl_id%20eq%20${this.guiApplId}`);
88
+ return response.data?.value || [];
89
+ }
90
+ catch (error) {
91
+ console.error('Failed to fetch columns:', error);
92
+ return [];
93
+ }
94
+ }
95
+ async getLookups() {
96
+ await this.ensureReady();
97
+ if (!this.isVerified || !this.guiApplId)
98
+ return [];
99
+ try {
100
+ const response = await this.axiosInstance.get(`/iam/${this.metaEndpoint}/i_ui_tab_look_up?$filter=gui_appl_id%20eq%20${this.guiApplId}`);
101
+ return response.data?.value || [];
102
+ }
103
+ catch (error) {
104
+ console.error('Failed to fetch lookups:', error);
105
+ return [];
106
+ }
107
+ }
108
+ async getScreenComponents() {
109
+ await this.ensureReady();
110
+ if (!this.isVerified || !this.guiApplId)
111
+ return [];
112
+ try {
113
+ const response = await this.axiosInstance.get(`/iam/${this.metaEndpoint}/i_ui_screen_component?$filter=gui_appl_id%20eq%20${this.guiApplId}`);
114
+ return response.data?.value || [];
115
+ }
116
+ catch (error) {
117
+ console.error('Failed to fetch screen components:', error);
118
+ return [];
119
+ }
120
+ }
121
+ /**
122
+ * Returns the verified GUI Application ID.
123
+ * Throws an error if verification failed or the alias was not found.
124
+ */
125
+ async getGuiApplId() {
126
+ await this.ensureReady();
127
+ if (this.isVerified && this.guiApplId !== null) {
128
+ return this.guiApplId;
129
+ }
130
+ const alias = testwiseConfig().get('environmentSettings.guiApplAlias');
131
+ throw new Error(`IndiciumApiService: Failed to resolve GUI Application ID for alias "${alias}".`);
132
+ }
133
+ }
134
+ export const indiciumApi = new IndiciumApiService();
135
+ //# sourceMappingURL=IndiciumApi.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndiciumApi.service.js","sourceRoot":"","sources":["../../services/IndiciumApi.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Locator } from '@playwright/test';
2
+ export declare class SubjectPageBase {
3
+ context: Locator;
4
+ constructor(rootContext: Locator);
5
+ }
@@ -0,0 +1,6 @@
1
+ export class SubjectPageBase {
2
+ constructor(rootContext) {
3
+ this.context = rootContext;
4
+ }
5
+ }
6
+ //# sourceMappingURL=SubjectPageBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubjectPageBase.js","sourceRoot":"","sources":["../../../templates/test-artifacts/SubjectPageBase.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAG1B,YAAY,WAAoB;QAC9B,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../templates/test-artifacts/screens/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../templates/test-artifacts/subjects/index.ts"],"names":[],"mappings":""}
@@ -4,5 +4,5 @@ export enum KnownElementTypes {
4
4
  Textarea = 'textarea',
5
5
  Checkbox = 'checkbox',
6
6
  Lookup = 'lookup',
7
- Column = 'column'
8
- }
7
+ Column = 'column_cells'
8
+ }
@@ -0,0 +1,7 @@
1
+ import { indiciumApi } from '../services/IndiciumApi.service.js';
2
+
3
+ export class ConfigChecker {
4
+ public async hasValidModelBuilderConfig(): Promise<boolean> {
5
+ return await indiciumApi.canConnectToProject();
6
+ }
7
+ }
@@ -7,7 +7,7 @@ import type { UniversalConfigOptions, UniversalLoginOptions } from '../types/ind
7
7
  import { pollUntil } from './Poll.js';
8
8
 
9
9
  const _dirname = path.dirname(fileURLToPath(import.meta.url));
10
- const configFixture = JSON.parse(fs.readFileSync(path.resolve(_dirname, '../config.json'), 'utf-8'));
10
+ const configFixture = JSON.parse(fs.readFileSync(path.resolve(_dirname, '../../config.json'), 'utf-8'));
11
11
 
12
12
  export class LoginHelper {
13
13
  private _page: Page;
@@ -2,4 +2,5 @@ import type { Locator } from '@playwright/test';
2
2
 
3
3
  export interface IComponentObjects {
4
4
  context: Locator;
5
+ mainHeader: Locator;
5
6
  }
@@ -2,4 +2,4 @@ export interface IRegisteredSubjects {
2
2
  subject: string;
3
3
  variant?: string;
4
4
  screen_type: string;
5
- }
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkwise/testwise",
3
- "version": "0.2.0-beta.3",
3
+ "version": "0.2.5",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,9 +24,10 @@
24
24
  "chalk": "^5.4.1",
25
25
  "csv-parse": "^5.6.0",
26
26
  "dotenv": "^17.2.2",
27
+ "playwright-bdd": "^8.4.2",
27
28
  "prettier": "^3.6.2",
28
29
  "prompts": "^2.4.2",
29
- "quicktype": "^23.2.6",
30
+ "quicktype-core": "^23.2.6",
30
31
  "rimraf": "^6.0.1",
31
32
  "ts-node": "^10.9.2",
32
33
  "typescript": "^5.8.3"
@@ -71,6 +72,7 @@
71
72
  "interfaces/",
72
73
  "test-artifacts/",
73
74
  "artifact-builder/",
74
- "**/config.json"
75
+ "**/config.json",
76
+ "templates/"
75
77
  ]
76
78
  }
@@ -1,27 +1,10 @@
1
- // import type { Page } from '@playwright/test';
2
1
  import type { Test } from '../types/Test.js';
3
-
4
- export type SubjectType = {
5
- none: unknown;
6
- };
7
-
8
- declare module '@playwright/test' {
9
- interface Page {
10
- subject: SubjectType;
11
- }
12
- }
13
-
14
2
  export class SubjectRegistry {
15
3
  private _test: Test;
16
4
 
17
5
  constructor(test: Test) {
18
- this._test = test.extend({
19
- page: async ({ page }, use) => {
20
- page.subject = {} as SubjectType;
21
-
22
- await use(page);
23
- }
24
- });
6
+ // Implementation of this class is in the templates folder, don't edit here
7
+ this._test = test;
25
8
  }
26
9
 
27
10
  get test() {
@@ -1,7 +1,6 @@
1
1
  export * from './GlobalComponents.js';
2
2
  export * from './GoToDeepLink.js';
3
3
  export * from './LoginFeatures.js';
4
- export * from './SubjectProvider.js';
5
4
  export * from './SubjectRegistry.js';
6
5
  export * from './UserSimulation.js';
7
6
  export * from './WaitEventHandler.js';
package/scripts/main.js CHANGED
@@ -1,82 +1,63 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import process from 'node:process';
5
- import { PathResolver } from '../dist/helpers/index.js';
6
- import { postinstall } from './postinstall.js';
7
- import { setup } from './setup.js';
8
- import { sync } from './sync.js';
9
-
10
- await setup();
11
- const { testwiseConfig } = await import('../dist/services/index.js');
12
- const config = testwiseConfig();
13
- const configBuilder = await config.load();
14
-
15
-
16
- if (process.argv[2] === 'postinstall') {
17
- if (!await verifiedSeedData()) process.exit(0);
18
-
19
- postinstall();
20
- } else if (process.argv[2] === 'sync') {
21
- if (!await verifiedSeedData()) process.exit(0);
22
-
23
- sync();
24
- } else {
25
- console.warn('Command unknown.');
26
- }
27
-
28
- async function verifiedSeedData() {
29
- const consumerRoot = new PathResolver().getConsumerRootDirectory();
30
- const seedDataDir = path.join(consumerRoot, 'seed-data');
31
- const subjectsJson = path.join(seedDataDir, 'subjects.json');
32
- const screensDir = path.join(seedDataDir, 'screen-schemas');
33
- const projectIsConfigured = await isConfigured();
34
-
35
- if (!fs.existsSync(seedDataDir)) {
36
- if (projectIsConfigured) {
37
- fs.mkdirSync(seedDataDir);
38
- fs.mkdirSync(screensDir);
39
-
40
- console.log('Created seed-data directory structure.');
41
- return true;
42
- }
43
-
44
- console.info('No seed-data directory found.');
45
- return false;
46
- }
47
-
48
- if (!fs.existsSync(subjectsJson) && !projectIsConfigured) {
49
- console.info('No subjects.json');
50
- return false;
51
- }
52
-
53
- if (!fs.existsSync(screensDir)) {
54
- if (projectIsConfigured) {
55
- fs.mkdirSync(screensDir);
56
- console.log('Created screen-schemas directory.');
57
- return true;
58
- }
59
-
60
- console.info('No screen-schemas directory found.');
61
- return false;
62
- }
63
-
64
- const screenFiles = fs.readdirSync(screensDir).filter((f) => f.endsWith('.json'));
65
- if (screenFiles.length === 0 && !projectIsConfigured) {
66
- console.info('No screen JSON files found in seed-data/screen-schemas');
67
- return false;
68
- }
69
- return true;
70
- }
71
-
72
- async function isConfigured() {
73
- const user = configBuilder.get('environmentSettings.authUser');
74
- const password = configBuilder.get('environmentSettings.authUserPassword');
75
- const guiApplAlias = configBuilder.get('environmentSettings.guiApplAlias');
76
-
77
- return Boolean(
78
- user && user !== 'ExampleUser' &&
79
- password && password !== 'ExamplePassword@1' &&
80
- guiApplAlias && guiApplAlias !== 'ExampleName'
81
- );
82
- }
1
+ #!/usr/bin/env node
2
+ import process from 'node:process';
3
+ import { postinstall } from './postinstall.js';
4
+ import { setup } from './setup.js';
5
+ import { sync } from './sync.js';
6
+
7
+ /**
8
+ * Main entry point for Testwise CLI commands
9
+ * @param {string[]} args - Command line arguments
10
+ */
11
+ async function main() {
12
+ try {
13
+ const command = process.argv[2];
14
+
15
+ if (!command) {
16
+ console.error('Error: No command provided.');
17
+ console.log('Usage: main.js <command>');
18
+ console.log('Available commands: postinstall, sync');
19
+ process.exit(1);
20
+ }
21
+
22
+ if (command === 'postinstall') {
23
+ await handlePostinstall();
24
+ } else if (command === 'sync') {
25
+ await handleSync();
26
+ } else {
27
+ console.error(`Error: Unknown command '${command}'.`);
28
+ console.log('Available commands: postinstall, sync');
29
+ process.exit(1);
30
+ }
31
+ } catch (error) {
32
+ console.error('Fatal error:', error.message);
33
+ process.exit(1);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Handle postinstall command
39
+ */
40
+ async function handlePostinstall() {
41
+ try {
42
+ await setup();
43
+ postinstall();
44
+ } catch (error) {
45
+ console.error('Postinstall failed:', error.message);
46
+ process.exit(1);
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Handle sync command
52
+ */
53
+ async function handleSync() {
54
+ try {
55
+ sync();
56
+ } catch (error) {
57
+ console.error('Sync failed:', error.message);
58
+ process.exit(1);
59
+ }
60
+ }
61
+
62
+ // Start the application
63
+ main();
@@ -1,42 +1,40 @@
1
-
2
-
3
- import { execSync } from 'node:child_process';
4
- import path from 'node:path';
5
- import process from 'node:process';
6
- import { fileURLToPath } from 'node:url';
7
- import { ArtifactManager } from '../dist/artifact-builder/index.js';
8
- import { testwiseConfig } from '../dist/services/ConfigBuilder.js';
9
- import { sync } from './sync.js';
10
-
11
- const _filename = fileURLToPath(import.meta.url);
12
- const _dirname = path.dirname(_filename);
13
-
14
- export async function postinstall() {
15
-
16
- try {
17
- const autoSync = testwiseConfig().get('featureSettings.other.autoSync') ?? true;
18
- if (!autoSync) return;
19
-
20
- const rootDir = path.resolve(_dirname, '..');
21
- const artifactManager = new ArtifactManager();
22
-
23
- if (artifactManager.backupExists()) {
24
- artifactManager.restoreBackup();
25
- console.info('Restored artifacts from backup.');
26
-
27
- // const { SubjectRegistration } = await import('../dist/artifact-builder/index.js');
28
- // new SubjectRegistration().run(); - do not remove: future feature
29
-
30
- execSync('npx tsc', { cwd: rootDir, stdio: 'inherit' });
31
-
32
- console.info('Postinstall restore process completed successfully.');
33
-
34
- return;
35
- }
36
-
37
- await sync();
38
- } catch (error) {
39
- console.error('Postinstall process failed:', error.message);
40
- process.exit(1);
41
- }
42
- }
1
+ import { execSync } from 'node:child_process';
2
+ import path from 'node:path';
3
+ import process from 'node:process';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { ArtifactManager } from '../dist/artifact-builder/index.js';
6
+ import { testwiseConfig } from '../dist/services/ConfigBuilder.js';
7
+ import { sync } from './sync.js';
8
+
9
+ const _filename = fileURLToPath(import.meta.url);
10
+ const _dirname = path.dirname(_filename);
11
+
12
+ export async function postinstall() {
13
+ try {
14
+ const autoSync = testwiseConfig().get('featureSettings.other.autoSync') ?? true;
15
+ if (!autoSync) return;
16
+
17
+ const rootDir = path.resolve(_dirname, '..');
18
+ const artifactManager = new ArtifactManager();
19
+
20
+ if (artifactManager.backupExists()) {
21
+ artifactManager.restoreBackup();
22
+ console.info('Restored artifacts from backup.');
23
+
24
+ // eslint-disable-next-line @typescript-eslint/naming-convention
25
+ const { SubjectRegistration } = await import('../dist/artifact-builder/index.js');
26
+ new SubjectRegistration().run();
27
+
28
+ execSync('npx tsc', { cwd: rootDir, stdio: 'inherit' });
29
+
30
+ console.info('Postinstall restore process completed successfully.');
31
+
32
+ return;
33
+ }
34
+
35
+ await sync();
36
+ } catch (error) {
37
+ console.error('Postinstall process failed:', error.message);
38
+ process.exit(1);
39
+ }
40
+ }
package/scripts/setup.js CHANGED
@@ -1,37 +1,37 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { PathResolver } from '../dist/helpers/index.js';
5
-
6
- const _filename = fileURLToPath(import.meta.url);
7
- const _dirname = path.dirname(_filename);
8
-
9
- export async function setup() {
10
- try {
11
- const consumerRoot = new PathResolver().getConsumerRootDirectory();
12
- const testwiseConfigFile = path.resolve(consumerRoot, 'Testwise.json');
13
- const testwiseConfigTemplateFile = path.join(_dirname, 'Testwise.template.json');
14
- const tsConfigFile = path.resolve(consumerRoot, 'tsconfig.json');
15
- const tsConfigTemplateFile = path.join(_dirname, 'tsconfig.template.json');
16
-
17
- let filesCreated = false;
18
-
19
- if (!fs.existsSync(testwiseConfigFile)) {
20
- fs.copyFileSync(testwiseConfigTemplateFile, testwiseConfigFile);
21
- console.info('Testwise.json config file created.');
22
- filesCreated = true;
23
- }
24
-
25
- if (!fs.existsSync(tsConfigFile)) {
26
- fs.copyFileSync(tsConfigTemplateFile, tsConfigFile);
27
- console.info('tsconfig.json config file created.');
28
- filesCreated = true;
29
- }
30
-
31
- if (!filesCreated) {
32
- await new Promise(resolve => setTimeout(resolve, 1000));
33
- }
34
- } catch (error) {
35
- console.error('Error during installation:', error.message);
36
- }
37
- }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { PathResolver } from '../dist/helpers/index.js';
5
+
6
+ const _filename = fileURLToPath(import.meta.url);
7
+ const _dirname = path.dirname(_filename);
8
+
9
+ export async function setup() {
10
+ try {
11
+ const consumerRoot = new PathResolver().getConsumerRootDirectory();
12
+ const testwiseConfigFile = path.resolve(consumerRoot, 'Testwise.json');
13
+ const testwiseConfigTemplateFile = path.join(_dirname, 'Testwise.template.json');
14
+ const tsConfigFile = path.resolve(consumerRoot, 'tsconfig.json');
15
+ const tsConfigTemplateFile = path.join(_dirname, 'tsconfig.template.json');
16
+
17
+ let filesCreated = false;
18
+
19
+ if (!fs.existsSync(testwiseConfigFile)) {
20
+ fs.copyFileSync(testwiseConfigTemplateFile, testwiseConfigFile);
21
+ console.info('Testwise.json config file created.');
22
+ filesCreated = true;
23
+ }
24
+
25
+ if (!fs.existsSync(tsConfigFile)) {
26
+ fs.copyFileSync(tsConfigTemplateFile, tsConfigFile);
27
+ console.info('tsconfig.json config file created.');
28
+ filesCreated = true;
29
+ }
30
+
31
+ if (!filesCreated) {
32
+ await new Promise((resolve) => setTimeout(resolve, 1000));
33
+ }
34
+ } catch (error) {
35
+ console.error('Error during installation:', error.message);
36
+ }
37
+ }