@tng-sh/js 0.0.1
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/LICENSE.md +32 -0
- package/bin/tng.js +289 -0
- package/binaries/go-ui-darwin-amd64 +0 -0
- package/binaries/go-ui-darwin-arm64 +0 -0
- package/binaries/go-ui-linux-amd64 +0 -0
- package/binaries/go-ui-linux-arm64 +0 -0
- package/index.d.ts +12 -0
- package/index.js +321 -0
- package/lib/config.js +31 -0
- package/lib/generateTestsUi.js +330 -0
- package/lib/goUiSession.js +349 -0
- package/lib/jsonSession.js +156 -0
- package/lib/saveFile.js +87 -0
- package/package.json +47 -0
- package/tng_sh_js.darwin-arm64.node +0 -0
- package/tng_sh_js.darwin-x64.node +0 -0
- package/tng_sh_js.linux-arm64-gnu.node +0 -0
- package/tng_sh_js.linux-x64-gnu.node +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
class JsonSession {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.running = false;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
start() {
|
|
7
|
+
this.running = true;
|
|
8
|
+
this.emitEvent('started', { message: 'TNG JSON Session Started' });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
stop() {
|
|
12
|
+
this.running = false;
|
|
13
|
+
this.emitEvent('stopped', { message: 'TNG JSON Session Stopped' });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
displayError(message) {
|
|
17
|
+
this.emitEvent('error', { message: this.stripColors(message) });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
displayWarning(message) {
|
|
21
|
+
this.emitEvent('warning', { message: this.stripColors(message) });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
displayInfo(message) {
|
|
25
|
+
this.emitEvent('info', { message: this.stripColors(message) });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
displayList(title, items) {
|
|
29
|
+
this.emitEvent('list', {
|
|
30
|
+
title: this.stripColors(title),
|
|
31
|
+
items: items
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
isRunning() {
|
|
36
|
+
return this.running;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ------------------------------------------------------------------
|
|
40
|
+
// Progress
|
|
41
|
+
// ------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
showProgress(title, callback) {
|
|
44
|
+
this.emitEvent('progress_start', { title });
|
|
45
|
+
|
|
46
|
+
const reporter = new JsonProgressReporter();
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const result = callback(reporter);
|
|
50
|
+
|
|
51
|
+
if (result && result.error) {
|
|
52
|
+
// Error handled by reporter or caller
|
|
53
|
+
} else {
|
|
54
|
+
this.emitEvent('progress_complete', {
|
|
55
|
+
message: result?.message || 'Done',
|
|
56
|
+
result: result
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
this.emitEvent('error', { message: error.message });
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ------------------------------------------------------------------
|
|
68
|
+
// Results Display
|
|
69
|
+
// ------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
showAuditResults(auditResult) {
|
|
72
|
+
this.emitEvent('result', auditResult);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
showTestResults(title, passed, failed, errors, total, results = []) {
|
|
76
|
+
this.emitEvent('test_results', {
|
|
77
|
+
title,
|
|
78
|
+
passed,
|
|
79
|
+
failed,
|
|
80
|
+
errors,
|
|
81
|
+
total,
|
|
82
|
+
results
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ------------------------------------------------------------------
|
|
87
|
+
// Errors & Warnings
|
|
88
|
+
// ------------------------------------------------------------------
|
|
89
|
+
|
|
90
|
+
showAuthError(message = 'Authentication failed') {
|
|
91
|
+
this.emitEvent('auth_error', { message });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
showConfigError(missing) {
|
|
95
|
+
this.emitEvent('config_error', { missing });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
showConfigMissing(missingItems) {
|
|
99
|
+
this.emitEvent('config_missing', { missing: missingItems });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
showSystemStatus(status) {
|
|
103
|
+
this.emitEvent('system_status', status);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
showNoItems(type) {
|
|
107
|
+
this.emitEvent('no_items', { type });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ------------------------------------------------------------------
|
|
111
|
+
// Private Methods
|
|
112
|
+
// ------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
stripColors(str) {
|
|
115
|
+
// Remove ANSI color codes
|
|
116
|
+
return str.replace(/\x1b\[\d+(;\d+)*m/g, '');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
emitEvent(type, data = {}) {
|
|
120
|
+
const event = { type, ...data };
|
|
121
|
+
console.log(JSON.stringify(event));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
class JsonProgressReporter {
|
|
126
|
+
constructor() {
|
|
127
|
+
this.step = 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
update(message, percent = null, options = {}) {
|
|
131
|
+
const { stepIncrement = true, explicitStep = null } = options;
|
|
132
|
+
const stepIdx = explicitStep !== null ? explicitStep : this.step;
|
|
133
|
+
|
|
134
|
+
const payload = {
|
|
135
|
+
type: 'progress_update',
|
|
136
|
+
message,
|
|
137
|
+
step: stepIdx
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
if (percent !== null) {
|
|
141
|
+
payload.percent = percent;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log(JSON.stringify(payload));
|
|
145
|
+
|
|
146
|
+
if (stepIncrement && explicitStep === null) {
|
|
147
|
+
this.step += 1;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
error(message) {
|
|
152
|
+
console.log(JSON.stringify({ type: 'error', message }));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = { JsonSession, JsonProgressReporter };
|
package/lib/saveFile.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const prettier = require('prettier');
|
|
5
|
+
|
|
6
|
+
const saveTestFile = async (testContent) => {
|
|
7
|
+
try {
|
|
8
|
+
const parsed = typeof testContent === 'string' ? JSON.parse(testContent) : testContent;
|
|
9
|
+
|
|
10
|
+
if (parsed.error) {
|
|
11
|
+
console.log(chalk.red.bold(`❌ API responded with an error: ${parsed.error}`));
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Extract content and metadata
|
|
16
|
+
let contentStr = null;
|
|
17
|
+
let metaSource = parsed;
|
|
18
|
+
|
|
19
|
+
if (parsed.file_content && typeof parsed.file_content === 'object') {
|
|
20
|
+
metaSource = parsed.file_content;
|
|
21
|
+
contentStr = metaSource.file_content || metaSource.test_file_content;
|
|
22
|
+
} else if (parsed.test_file_content && typeof parsed.test_file_content === 'object') {
|
|
23
|
+
metaSource = parsed.test_file_content;
|
|
24
|
+
contentStr = metaSource.file_content || metaSource.test_file_content;
|
|
25
|
+
} else {
|
|
26
|
+
contentStr = parsed.file_content || parsed.test_file_content;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!contentStr) {
|
|
30
|
+
console.log(chalk.red.bold('❌ API response missing file content string'));
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Resolve file path
|
|
35
|
+
let filePath = metaSource.test_file_path || metaSource.file_path || metaSource.file_name || metaSource.file ||
|
|
36
|
+
parsed.test_file_path || parsed.file_path || 'generated_test.js';
|
|
37
|
+
|
|
38
|
+
// Ensure it's in a tests directory if not already
|
|
39
|
+
const testsDir = 'tests';
|
|
40
|
+
if (!filePath.startsWith(`${testsDir}/`) && !filePath.includes('/')) {
|
|
41
|
+
filePath = path.join(testsDir, filePath);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Ensure JS/TS extension
|
|
45
|
+
if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {
|
|
46
|
+
filePath = filePath.replace(/\.[^.]+$/, '') + '.js';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Add timestamp prefix (mirroring python logic)
|
|
50
|
+
const hasTimestamp = /^\d+_/.test(path.basename(filePath));
|
|
51
|
+
if (!hasTimestamp) {
|
|
52
|
+
const timestamp = new Date().toISOString().replace(/[-:T]/g, '').split('.')[0];
|
|
53
|
+
filePath = path.join(path.dirname(filePath), `${timestamp}_${path.basename(filePath)}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const absolutePath = path.resolve(filePath);
|
|
57
|
+
const dir = path.dirname(absolutePath);
|
|
58
|
+
if (!fs.existsSync(dir)) {
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Format with Prettier
|
|
63
|
+
let formattedContent = contentStr;
|
|
64
|
+
try {
|
|
65
|
+
const prettierOptions = (await prettier.resolveConfig(absolutePath)) || { semi: true, singleQuote: true, parser: 'babel' };
|
|
66
|
+
// Fallback parser if filepath doesn't help
|
|
67
|
+
if (!prettierOptions.parser) prettierOptions.parser = 'babel';
|
|
68
|
+
formattedContent = prettier.format(contentStr, { ...prettierOptions, filepath: absolutePath });
|
|
69
|
+
} catch (prettierError) {
|
|
70
|
+
// Best effort formatting
|
|
71
|
+
console.log(chalk.yellow(`⚠ Prettier formatting failed, saving raw: ${prettierError.message}`));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fs.writeFileSync(absolutePath, formattedContent);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
file_path: filePath,
|
|
78
|
+
absolute_path: absolutePath,
|
|
79
|
+
framework: metaSource.framework || parsed.framework || 'jest'
|
|
80
|
+
};
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.log(chalk.red.bold(`❌ Failed to save test file: ${error.message}`));
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
module.exports = { saveTestFile };
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tng-sh/js",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "TNG JavaScript core - HTTP transport and utilities",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/tng-sh/tng-js-public.git"
|
|
8
|
+
},
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/tng-sh/tng-js-public/issues"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/tng-sh/tng-js-public#readme",
|
|
13
|
+
"main": "index.js",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"tng": "bin/tng.js"
|
|
19
|
+
},
|
|
20
|
+
"types": "index.d.ts",
|
|
21
|
+
"napi": {
|
|
22
|
+
"binaryName": "tng_sh_js",
|
|
23
|
+
"targets": [
|
|
24
|
+
"x86_64-apple-darwin",
|
|
25
|
+
"aarch64-apple-darwin",
|
|
26
|
+
"x86_64-unknown-linux-gnu",
|
|
27
|
+
"aarch64-unknown-linux-gnu"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "napi build --platform --release",
|
|
32
|
+
"build:debug": "napi build --platform",
|
|
33
|
+
"test": "node test.js"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@napi-rs/cli": "^2.18.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">= 10"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"chalk": "^4.1.2",
|
|
43
|
+
"commander": "^14.0.2",
|
|
44
|
+
"fast-glob": "^3.3.3",
|
|
45
|
+
"prettier": "^2.8.8"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|