maiass 5.7.31

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,152 @@
1
+ // Complete list of MAIASS environment variables with their defaults
2
+ // Extracted from setup_bumpscript_variables() in maiass.sh
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+
6
+ export const MAIASS_VARIABLES = {
7
+ // Core system variables
8
+ 'MAIASS_DEBUG': { default: 'false', description: 'Enable debug mode' },
9
+ 'MAIASS_AUTOPUSH_COMMITS': { default: 'false', description: 'Automatically push commits' },
10
+ 'MAIASS_BRAND': { default: 'MAIASS', description: 'Brand name for display' },
11
+ 'MAIASS_VERBOSITY': { default: 'brief', description: 'Verbosity level (brief/normal/verbose)' },
12
+ 'MAIASS_LOGGING': { default: 'false', description: 'Enable logging to file' },
13
+ 'MAIASS_LOG_FILE': { default: 'maiass.log', description: 'Log file name' },
14
+
15
+ // AI configuration
16
+ 'MAIASS_AI_MODE': { default: 'ask', description: 'AI interaction mode' },
17
+ 'MAIASS_AI_TOKEN': { default: '', description: 'AI API token', sensitive: true },
18
+ 'MAIASS_AI_MODEL': { default: 'gpt-3.5-turbo', description: 'AI model to use' },
19
+ 'MAIASS_AI_TEMPERATURE': { default: '0.7', description: 'AI temperature setting' },
20
+ 'MAIASS_AI_MAX_CHARACTERS': { default: '8000', description: 'Max characters for AI requests' },
21
+ 'MAIASS_AI_COMMIT_MESSAGE_STYLE': { default: 'bullet', description: 'Commit message style' },
22
+
23
+ // Version file system
24
+ 'MAIASS_VERSION_PRIMARY_FILE': { default: '', description: 'Primary version file path' },
25
+ 'MAIASS_VERSION_PRIMARY_TYPE': { default: '', description: 'Primary version file type' },
26
+ 'MAIASS_VERSION_PRIMARY_LINE_START': { default: '', description: 'Line start pattern for version' },
27
+ 'MAIASS_VERSION_SECONDARY_FILES': { default: '', description: 'Secondary version files (comma-separated)' },
28
+
29
+ // Branch configuration
30
+ 'MAIASS_DEVELOPBRANCH': { default: 'develop', description: 'Development branch name' },
31
+ 'MAIASS_STAGINGBRANCH': { default: 'staging', description: 'Staging branch name' },
32
+ 'MAIASS_MAINBRANCH': { default: 'main', description: 'Main/Master branch name' },
33
+
34
+ // Changelog configuration
35
+ 'MAIASS_CHANGELOG_PATH': { default: '.', description: 'Path to changelog directory' },
36
+ 'MAIASS_CHANGELOG_NAME': { default: 'CHANGELOG.md', description: 'Main changelog filename' },
37
+ 'MAIASS_CHANGELOG_INTERNAL_NAME': { default: '.CHANGELOG_internal.md', description: 'Internal changelog filename' },
38
+
39
+ // Repository configuration
40
+ 'MAIASS_REPO_TYPE': { default: 'bespoke', description: 'Repository type (wordpress-theme/plugin/site, craft, bespoke)' },
41
+ 'MAIASS_VERSION_PATH': { default: '.', description: 'Path to version files' },
42
+ 'MAIASS_PACKAGE_PATH': { default: '.', description: 'Path to package.json' },
43
+ 'MAIASS_WP_FILES_PATH': { default: '', description: 'Path to WordPress files' },
44
+
45
+ // Release configuration
46
+ 'MAIASS_AUTO_TAG_RELEASES': { default: 'true', description: 'Automatically tag releases without prompting' },
47
+
48
+ // Pull request configuration
49
+ 'MAIASS_STAGING_PULLREQUESTS': { default: 'on', description: 'Enable staging pull requests' },
50
+ 'MAIASS_MAIN_PULLREQUESTS': { default: 'on', description: 'Enable main branch pull requests' },
51
+
52
+ // Repository provider configuration
53
+ 'MAIASS_BITBUCKET_WORKSPACE': { default: '', description: 'Bitbucket workspace name' },
54
+ 'MAIASS_BITBUCKET_REPO_SLUG': { default: '', description: 'Bitbucket repository slug' },
55
+ 'MAIASS_GITHUB_OWNER': { default: '', description: 'GitHub repository owner' },
56
+ 'MAIASS_GITHUB_REPO': { default: '', description: 'GitHub repository name' }
57
+ };
58
+
59
+ /**
60
+ * Get the source of an environment variable value
61
+ * @param {string} key - Environment variable key
62
+ * @param {string} value - Current value
63
+ * @param {Array} loadedFiles - Array of loaded config files
64
+ * @returns {string} Source description
65
+ */
66
+ export function getVariableSource(key, value, loadedFiles) {
67
+ const varDef = MAIASS_VARIABLES[key];
68
+
69
+ if (!value) {
70
+ return 'not set';
71
+ }
72
+
73
+ if (varDef && value === varDef.default) {
74
+ return 'default';
75
+ }
76
+
77
+ // Check which file contains this variable by reading file contents
78
+ // Priority order: .env.maiass.local (highest) -> .env.maiass -> user .maiass.env -> OS config -> OS secure (lowest)
79
+
80
+ // Check project .env.maiass.local first (highest priority)
81
+ const projectLocalEnv = path.resolve(process.cwd(), '.env.maiass.local');
82
+ if (fs.existsSync(projectLocalEnv)) {
83
+ try {
84
+ const content = fs.readFileSync(projectLocalEnv, 'utf8');
85
+ // Use more precise regex to match the exact variable
86
+ const regex = new RegExp(`^\\s*${key}\\s*=`, 'm');
87
+ if (regex.test(content)) {
88
+ return 'project local';
89
+ }
90
+ } catch (error) {
91
+ // File read error, continue checking other files
92
+ }
93
+ }
94
+
95
+ // Check project .env.maiass (second priority)
96
+ const projectEnv = path.resolve(process.cwd(), '.env.maiass');
97
+ if (fs.existsSync(projectEnv)) {
98
+ try {
99
+ const content = fs.readFileSync(projectEnv, 'utf8');
100
+ const regex = new RegExp(`^\\s*${key}\\s*=`, 'm');
101
+ if (regex.test(content)) {
102
+ return 'project';
103
+ }
104
+ } catch (error) {
105
+ // File read error, continue checking other files
106
+ }
107
+ }
108
+
109
+ // Check user .maiass.env (global user config)
110
+ const userEnv = loadedFiles.find(f => f.includes('.maiass.env'));
111
+ if (userEnv) {
112
+ try {
113
+ const content = fs.readFileSync(userEnv, 'utf8');
114
+ const regex = new RegExp(`^\\s*${key}\\s*=`, 'm');
115
+ if (regex.test(content)) {
116
+ return 'global';
117
+ }
118
+ } catch (error) {
119
+ // File read error, continue checking other files
120
+ }
121
+ }
122
+
123
+ // Check OS config
124
+ const osConfig = loadedFiles.find(f => f.includes('config.env'));
125
+ if (osConfig) {
126
+ try {
127
+ const content = fs.readFileSync(osConfig, 'utf8');
128
+ if (content.includes(`${key}=`)) {
129
+ return 'OS config';
130
+ }
131
+ } catch (error) {
132
+ // File read error, continue checking other files
133
+ }
134
+ }
135
+
136
+ // Check OS secure
137
+ const osSecure = loadedFiles.find(f => f.includes('secure.env'));
138
+ if (osSecure) {
139
+ try {
140
+ const content = fs.readFileSync(osSecure, 'utf8');
141
+ if (content.includes(`${key}=`)) {
142
+ return 'OS secure';
143
+ }
144
+ } catch (error) {
145
+ // File read error, continue checking other files
146
+ }
147
+ }
148
+
149
+ return 'environment';
150
+ }
151
+
152
+ export default MAIASS_VARIABLES;
@@ -0,0 +1,256 @@
1
+ // Secure storage functionality for nodemaiass
2
+ // Uses OS keychain (macOS) or secret-tool (Linux) for sensitive data storage
3
+ // Compatible with bashmaiass approach but uses NODEMAIASS service names
4
+
5
+ import { execSync } from 'child_process';
6
+ import os from 'os';
7
+ import { log } from './logger.js';
8
+ import { SYMBOLS } from './symbols.js';
9
+
10
+ /**
11
+ * Get environment-specific service name for secure storage
12
+ * Uses NODEMAIASS prefix to differentiate from bashmaiass
13
+ * @returns {string} Service name for secure storage
14
+ */
15
+ export function getSecureServiceName() {
16
+ const env = process.env.MAIASS_AI_HOST || '';
17
+ let envSuffix = '';
18
+
19
+ if (env.includes('localhost') || env.includes('127.0.0.1')) {
20
+ envSuffix = '_localhost';
21
+ } else if (env.includes('preview') || env.includes('staging')) {
22
+ envSuffix = '_preview';
23
+ }
24
+ // Production uses no suffix
25
+
26
+ // Use 'maiass' (not 'nodemaiass') to share keychain with bashmaiass
27
+ return `maiass${envSuffix}`;
28
+ }
29
+
30
+ /**
31
+ * Store a sensitive variable in OS secure storage
32
+ * @param {string} varName - Variable name (e.g., 'MAIASS_AI_TOKEN')
33
+ * @param {string} varValue - Variable value
34
+ * @returns {boolean} Success status
35
+ */
36
+ export function storeSecureVariable(varName, varValue) {
37
+ const serviceName = getSecureServiceName();
38
+ const debugMode = process.env.MAIASS_DEBUG === 'true';
39
+
40
+ if (debugMode) {
41
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Storing ${varName} in secure storage service: ${serviceName}`);
42
+ }
43
+
44
+ try {
45
+ if (os.platform() === 'darwin') {
46
+ // macOS: Use keychain via security command
47
+ execSync(`security add-generic-password -U -s "${serviceName}" -a "${varName}" -w "${varValue}"`, {
48
+ stdio: 'pipe'
49
+ });
50
+ } else {
51
+ // Linux: Use secret-tool if available
52
+ try {
53
+ execSync('which secret-tool', { stdio: 'pipe' });
54
+ execSync(`echo -n "${varValue}" | secret-tool store --label="NODEMAIASS ${varName} (${serviceName})" service "${serviceName}" key "${varName}"`, {
55
+ stdio: 'pipe',
56
+ shell: true
57
+ });
58
+ } catch (error) {
59
+ if (debugMode) {
60
+ log.debug(SYMBOLS.WARNING, '[MAIASS DEBUG] secret-tool not available, secure storage not supported on this system');
61
+ }
62
+ return false;
63
+ }
64
+ }
65
+
66
+ if (debugMode) {
67
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Successfully stored ${varName} in secure storage`);
68
+ }
69
+ return true;
70
+ } catch (error) {
71
+ if (debugMode) {
72
+ log.debug(SYMBOLS.WARNING, `[MAIASS DEBUG] Failed to store ${varName} in secure storage: ${error.message}`);
73
+ }
74
+ return false;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Retrieve a sensitive variable from OS secure storage
80
+ * @param {string} varName - Variable name (e.g., 'MAIASS_AI_TOKEN')
81
+ * @returns {string|null} Variable value or null if not found
82
+ */
83
+ export function retrieveSecureVariable(varName) {
84
+ const serviceName = getSecureServiceName();
85
+ const debugMode = process.env.MAIASS_DEBUG === 'true';
86
+
87
+ if (debugMode) {
88
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Retrieving ${varName} from secure storage service: ${serviceName}`);
89
+ }
90
+
91
+ try {
92
+ let value = null;
93
+
94
+ if (os.platform() === 'darwin') {
95
+ // macOS: Use keychain via security command
96
+ value = execSync(`security find-generic-password -s "${serviceName}" -a "${varName}" -w`, {
97
+ stdio: 'pipe',
98
+ encoding: 'utf8'
99
+ }).trim();
100
+ } else {
101
+ // Linux: Use secret-tool if available
102
+ try {
103
+ execSync('which secret-tool', { stdio: 'pipe' });
104
+ value = execSync(`secret-tool lookup service "${serviceName}" key "${varName}"`, {
105
+ stdio: 'pipe',
106
+ encoding: 'utf8'
107
+ }).trim();
108
+ } catch (error) {
109
+ if (debugMode) {
110
+ log.debug(SYMBOLS.WARNING, '[MAIASS DEBUG] secret-tool not available, secure storage not supported on this system');
111
+ }
112
+ return null;
113
+ }
114
+ }
115
+
116
+ if (debugMode && value) {
117
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Successfully retrieved ${varName} from secure storage`);
118
+ }
119
+
120
+ return value || null;
121
+ } catch (error) {
122
+ if (debugMode) {
123
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] ${varName} not found in secure storage (this is normal for first run)`);
124
+ }
125
+ return null;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Remove a sensitive variable from OS secure storage
131
+ * @param {string} varName - Variable name (e.g., 'MAIASS_AI_TOKEN')
132
+ * @returns {boolean} Success status
133
+ */
134
+ export function removeSecureVariable(varName) {
135
+ const serviceName = getSecureServiceName();
136
+ const debugMode = process.env.MAIASS_DEBUG === 'true';
137
+
138
+ if (debugMode) {
139
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Removing ${varName} from secure storage service: ${serviceName}`);
140
+ }
141
+
142
+ try {
143
+ if (os.platform() === 'darwin') {
144
+ // macOS: Use keychain via security command
145
+ execSync(`security delete-generic-password -s "${serviceName}" -a "${varName}"`, {
146
+ stdio: 'pipe'
147
+ });
148
+ } else {
149
+ // Linux: secret-tool doesn't have direct delete, but we can try to clear it
150
+ try {
151
+ execSync('which secret-tool', { stdio: 'pipe' });
152
+ // secret-tool doesn't have a delete command, so we store an empty value
153
+ execSync(`echo -n "" | secret-tool store --label="NODEMAIASS ${varName} (${serviceName})" service "${serviceName}" key "${varName}"`, {
154
+ stdio: 'pipe',
155
+ shell: true
156
+ });
157
+ } catch (error) {
158
+ if (debugMode) {
159
+ log.debug(SYMBOLS.WARNING, '[MAIASS DEBUG] secret-tool not available, secure storage not supported on this system');
160
+ }
161
+ return false;
162
+ }
163
+ }
164
+
165
+ if (debugMode) {
166
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Successfully removed ${varName} from secure storage`);
167
+ }
168
+ return true;
169
+ } catch (error) {
170
+ if (debugMode) {
171
+ log.debug(SYMBOLS.WARNING, `[MAIASS DEBUG] Failed to remove ${varName} from secure storage: ${error.message}`);
172
+ }
173
+ return false;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Load secure variables into environment
179
+ * Loads MAIASS_AI_TOKEN and MAIASS_SUBSCRIPTION_ID from secure storage
180
+ */
181
+ export function loadSecureVariables() {
182
+ const secureVars = ['MAIASS_AI_TOKEN', 'MAIASS_SUBSCRIPTION_ID'];
183
+ const debugMode = process.env.MAIASS_DEBUG === 'true';
184
+ const serviceName = getSecureServiceName();
185
+
186
+ if (debugMode) {
187
+ const host = process.env.MAIASS_AI_HOST || 'https://pound.maiass.net';
188
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Using secure storage service name: ${serviceName} (host: ${host})`);
189
+ }
190
+
191
+ secureVars.forEach(varName => {
192
+ const envValue = process.env[varName];
193
+
194
+ if (debugMode) {
195
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Checking ${varName}: value="${envValue}", type=${typeof envValue}, empty=${!envValue || envValue.trim() === ''}`);
196
+ }
197
+
198
+ // Check if we should prefer secure storage over environment variable
199
+ let preferSecure = false;
200
+ if (varName === 'MAIASS_AI_TOKEN' && envValue) {
201
+ // Check if the existing token looks invalid
202
+ if (/^invalid_|^test_|_test$/.test(envValue) || envValue === 'DISABLED' || envValue.trim() === '') {
203
+ preferSecure = true;
204
+ if (debugMode) {
205
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Environment token appears invalid, checking secure storage`);
206
+ }
207
+ }
208
+ }
209
+
210
+ // Only load if not already set with valid token (unless we want to prefer secure storage)
211
+ if (!envValue || envValue.trim() === '' || preferSecure) {
212
+ const value = retrieveSecureVariable(varName);
213
+ if (value) {
214
+ process.env[varName] = value;
215
+ if (preferSecure) {
216
+ if (debugMode) {
217
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Replaced invalid environment token with secure storage token`);
218
+ }
219
+ } else {
220
+ if (debugMode) {
221
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] Loaded ${varName} from secure storage`);
222
+ }
223
+ }
224
+ }
225
+ } else if (debugMode) {
226
+ log.debug(SYMBOLS.INFO, `[MAIASS DEBUG] ${varName} already set in environment, skipping secure storage`);
227
+ }
228
+ });
229
+ }
230
+
231
+ /**
232
+ * Check if secure storage is available on this system
233
+ * @returns {boolean} True if secure storage is supported
234
+ */
235
+ export function isSecureStorageAvailable() {
236
+ try {
237
+ if (os.platform() === 'darwin') {
238
+ execSync('which security', { stdio: 'pipe' });
239
+ return true;
240
+ } else {
241
+ execSync('which secret-tool', { stdio: 'pipe' });
242
+ return true;
243
+ }
244
+ } catch (error) {
245
+ return false;
246
+ }
247
+ }
248
+
249
+ export default {
250
+ getSecureServiceName,
251
+ storeSecureVariable,
252
+ retrieveSecureVariable,
253
+ removeSecureVariable,
254
+ loadSecureVariables,
255
+ isSecureStorageAvailable
256
+ };
package/lib/symbols.js ADDED
@@ -0,0 +1,200 @@
1
+ // Cross-platform symbol system with Unicode/ASCII fallbacks
2
+ import os from 'os';
3
+
4
+ /**
5
+ * Detect if the current terminal supports Unicode
6
+ * @returns {boolean} True if Unicode is supported
7
+ */
8
+ function supportsUnicode() {
9
+ // Check environment variable override
10
+ if (process.env.MAIASS_NO_UNICODE === 'true') {
11
+ return false;
12
+ }
13
+
14
+ // Force Unicode if explicitly enabled
15
+ if (process.env.MAIASS_FORCE_UNICODE === 'true') {
16
+ return true;
17
+ }
18
+
19
+ // Check platform and terminal capabilities
20
+ const platform = os.platform();
21
+
22
+ // Windows-specific checks
23
+ if (platform === 'win32') {
24
+ // Modern Windows Terminal supports Unicode
25
+ if (process.env.WT_SESSION) {
26
+ return true;
27
+ }
28
+
29
+ // PowerShell 7+ generally supports Unicode
30
+ if (process.env.PSModulePath && process.env.POWERSHELL_DISTRIBUTION_CHANNEL) {
31
+ return true;
32
+ }
33
+
34
+ // VS Code integrated terminal
35
+ if (process.env.VSCODE_INJECTION || process.env.TERM_PROGRAM === 'vscode') {
36
+ return true;
37
+ }
38
+
39
+ // Default to ASCII for Windows cmd and older terminals
40
+ return false;
41
+ }
42
+
43
+ // macOS and Linux generally support Unicode
44
+ if (platform === 'darwin' || platform === 'linux') {
45
+ // Check if we're in a known Unicode-capable terminal
46
+ const term = process.env.TERM || '';
47
+ const termProgram = process.env.TERM_PROGRAM || '';
48
+
49
+ if (term.includes('xterm') ||
50
+ term.includes('screen') ||
51
+ termProgram === 'vscode' ||
52
+ termProgram === 'iTerm.app' ||
53
+ process.env.COLORTERM === 'truecolor') {
54
+ return true;
55
+ }
56
+ }
57
+
58
+ // Default to Unicode for non-Windows platforms
59
+ return platform !== 'win32';
60
+ }
61
+
62
+ /**
63
+ * Symbol definitions with Unicode and ASCII fallbacks
64
+ */
65
+ const SYMBOL_SETS = {
66
+ unicode: {
67
+ globe: '🌍',
68
+ folder: '📁',
69
+ gear: 'âš™ī¸',
70
+ wrench: '🔧',
71
+ checkmark: '✅',
72
+ cross: '❌',
73
+ warning: 'âš ī¸',
74
+ info: 'â„šī¸',
75
+ smile: '😊',
76
+ sunglasses: '😎',
77
+ poo: '💩',
78
+ rocket: '🚀',
79
+ arrow: '→',
80
+ check: '✓',
81
+ x: '✗',
82
+ bullet: 'â€ĸ',
83
+ diamond: '◆',
84
+ star: '★',
85
+ heart: 'â™Ĩ',
86
+ spade: '♠',
87
+ club: 'â™Ŗ',
88
+ maiassdot: '(.)',
89
+ maiassass: '|))',
90
+ pushing: '↑↑↑',
91
+ merging: '<=>',
92
+ pulling: '↓↓↓',
93
+ brain: '🧠',
94
+ },
95
+ ascii: {
96
+ globe: '[GLOBE]',
97
+ folder: '[FOLDER]',
98
+ gear: '[GEAR]',
99
+ wrench: '[TOOL]',
100
+ checkmark: '[OK]',
101
+ cross: '[ERROR]',
102
+ warning: '[WARN]',
103
+ info: '[INFO]',
104
+ smile: ':)',
105
+ sunglasses: ':D',
106
+ poo: ':(',
107
+ rocket: '[ROCKET]',
108
+ arrow: '->',
109
+ check: '+',
110
+ x: '-',
111
+ bullet: '*',
112
+ diamond: '<>',
113
+ star: '*',
114
+ heart: '<3',
115
+ spade: 'S',
116
+ club: 'C',
117
+ maiassdot: '(.)',
118
+ maiassass: '|))',
119
+ pushing: '↑↑↑',
120
+ merging: '<=>',
121
+ pulling: '↓↓↓',
122
+ brain: '[AI]',}
123
+ };
124
+
125
+ /**
126
+ * Get the appropriate symbol set based on terminal capabilities
127
+ */
128
+ const useUnicode = supportsUnicode();
129
+ const symbols = useUnicode ? SYMBOL_SETS.unicode : SYMBOL_SETS.ascii;
130
+
131
+ /**
132
+ * Get a symbol with automatic Unicode/ASCII fallback
133
+ * @param {string} name - Symbol name
134
+ * @returns {string} The appropriate symbol for the current terminal
135
+ */
136
+ export function getSymbol(name) {
137
+ return symbols[name] || name;
138
+ }
139
+
140
+ /**
141
+ * Check if Unicode is being used
142
+ * @returns {boolean} True if Unicode symbols are active
143
+ */
144
+ export function isUnicodeEnabled() {
145
+ return useUnicode;
146
+ }
147
+
148
+ /**
149
+ * Get terminal info for debugging
150
+ * @returns {Object} Terminal capability information
151
+ */
152
+ export function getTerminalInfo() {
153
+ return {
154
+ platform: os.platform(),
155
+ supportsUnicode: useUnicode,
156
+ env: {
157
+ TERM: process.env.TERM,
158
+ TERM_PROGRAM: process.env.TERM_PROGRAM,
159
+ COLORTERM: process.env.COLORTERM,
160
+ WT_SESSION: process.env.WT_SESSION,
161
+ VSCODE_INJECTION: process.env.VSCODE_INJECTION,
162
+ MAIASS_NO_UNICODE: process.env.MAIASS_NO_UNICODE,
163
+ MAIASS_FORCE_UNICODE: process.env.MAIASS_FORCE_UNICODE
164
+ }
165
+ };
166
+ }
167
+
168
+ // Export individual symbols for convenience
169
+ export const SYMBOLS = {
170
+ GLOBE: getSymbol('globe'),
171
+ FOLDER: getSymbol('folder'),
172
+ GEAR: getSymbol('gear'),
173
+ WRENCH: getSymbol('wrench'),
174
+ CHECKMARK: getSymbol('checkmark'),
175
+ CROSS: getSymbol('cross'),
176
+ WARNING: getSymbol('warning'),
177
+ INFO: getSymbol('info'),
178
+ ARROW: getSymbol('arrow'),
179
+ CHECK: getSymbol('check'),
180
+ X: getSymbol('x'),
181
+ BULLET: getSymbol('bullet'),
182
+ DIAMOND: getSymbol('diamond'),
183
+ STAR: getSymbol('star'),
184
+ HEART: getSymbol('heart'),
185
+ SPADE: getSymbol('spade'),
186
+ CLUB: getSymbol('club'),
187
+ MAIASSDOT: getSymbol('maiassdot'),
188
+ MAIASSASS: getSymbol('maiassass'),
189
+ PUSHING: getSymbol('pushing'),
190
+ MERGING: getSymbol('merging'),
191
+ PULLING: getSymbol('pulling'),
192
+ BRAIN: getSymbol('brain')
193
+ };
194
+
195
+ export default {
196
+ getSymbol,
197
+ isUnicodeEnabled,
198
+ getTerminalInfo,
199
+ SYMBOLS
200
+ };