@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.
@@ -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 };
@@ -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