@tothalex/nulljs 0.0.48 → 0.0.54

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 (42) hide show
  1. package/package.json +25 -32
  2. package/scripts/install-server.js +0 -199
  3. package/src/commands/api.ts +0 -16
  4. package/src/commands/auth.ts +0 -54
  5. package/src/commands/create.ts +0 -43
  6. package/src/commands/deploy.ts +0 -160
  7. package/src/commands/dev/function/index.ts +0 -221
  8. package/src/commands/dev/function/utils.ts +0 -99
  9. package/src/commands/dev/index.tsx +0 -126
  10. package/src/commands/dev/logging-manager.ts +0 -87
  11. package/src/commands/dev/server/index.ts +0 -48
  12. package/src/commands/dev/server/utils.ts +0 -37
  13. package/src/commands/dev/ui/components/scroll-area.tsx +0 -141
  14. package/src/commands/dev/ui/components/tab-bar.tsx +0 -67
  15. package/src/commands/dev/ui/index.tsx +0 -71
  16. package/src/commands/dev/ui/logging-context.tsx +0 -76
  17. package/src/commands/dev/ui/tabs/functions-tab.tsx +0 -35
  18. package/src/commands/dev/ui/tabs/server-tab.tsx +0 -36
  19. package/src/commands/dev/ui/tabs/vite-tab.tsx +0 -35
  20. package/src/commands/dev/ui/use-logging.tsx +0 -34
  21. package/src/commands/dev/vite/index.ts +0 -54
  22. package/src/commands/dev/vite/utils.ts +0 -71
  23. package/src/commands/host.ts +0 -339
  24. package/src/commands/index.ts +0 -8
  25. package/src/commands/profile.ts +0 -189
  26. package/src/commands/secret.ts +0 -79
  27. package/src/index.ts +0 -346
  28. package/src/lib/api.ts +0 -189
  29. package/src/lib/bundle/external.ts +0 -23
  30. package/src/lib/bundle/function/index.ts +0 -46
  31. package/src/lib/bundle/index.ts +0 -2
  32. package/src/lib/bundle/react/index.ts +0 -2
  33. package/src/lib/bundle/react/spa.ts +0 -77
  34. package/src/lib/bundle/react/ssr/client.ts +0 -93
  35. package/src/lib/bundle/react/ssr/config.ts +0 -77
  36. package/src/lib/bundle/react/ssr/index.ts +0 -4
  37. package/src/lib/bundle/react/ssr/props.ts +0 -71
  38. package/src/lib/bundle/react/ssr/server.ts +0 -83
  39. package/src/lib/bundle/types.ts +0 -4
  40. package/src/lib/config.ts +0 -347
  41. package/src/lib/deployment.ts +0 -244
  42. package/src/lib/update-server.ts +0 -262
@@ -1,339 +0,0 @@
1
- import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'node:fs'
2
- import { join, resolve, dirname } from 'node:path'
3
- import { execSync } from 'node:child_process'
4
- import { homedir } from 'node:os'
5
- import { fileURLToPath } from 'node:url'
6
- import chalk from 'chalk'
7
- import { updateServer } from '../lib/update-server'
8
-
9
- const getServerBinPath = (): string => {
10
- // Try to find the server binary relative to this module
11
- // This works both in development and when installed globally
12
- const currentFile = fileURLToPath(import.meta.url)
13
- const moduleRoot = resolve(dirname(currentFile), '../..')
14
- return join(moduleRoot, 'bin', 'server')
15
- }
16
-
17
- type ProductionConfig = {
18
- key: {
19
- private: string
20
- public: string
21
- }
22
- }
23
-
24
- const generateProductionKeys = async (): Promise<{ privateKey: string; publicKey: string }> => {
25
- console.log(chalk.blue('🔑 Generating production keys...'))
26
-
27
- const keyPair = await crypto.subtle.generateKey(
28
- {
29
- name: 'Ed25519',
30
- namedCurve: 'Ed25519'
31
- },
32
- true,
33
- ['sign', 'verify']
34
- )
35
-
36
- const privateKeyBuffer = await crypto.subtle.exportKey('pkcs8', keyPair.privateKey)
37
- const publicKeyBuffer = await crypto.subtle.exportKey('spki', keyPair.publicKey)
38
-
39
- const privateKey = btoa(String.fromCharCode(...new Uint8Array(privateKeyBuffer)))
40
- const publicKey = btoa(String.fromCharCode(...new Uint8Array(publicKeyBuffer)))
41
-
42
- return { privateKey, publicKey }
43
- }
44
-
45
- const saveProductionConfig = (cloudPath: string, privateKey: string, publicKey: string): void => {
46
- const configPath = join(cloudPath, 'config.json')
47
- const config: ProductionConfig = {
48
- key: {
49
- private: privateKey,
50
- public: publicKey
51
- }
52
- }
53
-
54
- console.log(chalk.blue('💾 Saving production configuration...'))
55
- writeFileSync(configPath, JSON.stringify(config, null, 2))
56
-
57
- // Set proper permissions on the config file (readable only by owner)
58
- execSync(`chmod 600 ${configPath}`, { stdio: 'inherit' })
59
-
60
- console.log(chalk.green('✅ Production configuration saved'))
61
- }
62
-
63
- const createSystemdService = (cloudPath: string, publicKey: string, serverBinPath: string, userName: string) => {
64
- const serviceContent = `
65
- [Unit]
66
- Description=NullJS Server
67
- After=network.target
68
- StartLimitIntervalSec=0
69
-
70
- [Service]
71
- Type=simple
72
- Restart=always
73
- RestartSec=1
74
- User=${userName}
75
- ExecStart=${serverBinPath}
76
- Environment=CLOUD_PATH=${cloudPath}
77
- Environment=PUBLIC_KEY=${publicKey}
78
- WorkingDirectory=${cloudPath}
79
-
80
- [Install]
81
- WantedBy=multi-user.target
82
- `
83
-
84
- return serviceContent
85
- }
86
-
87
-
88
- const ensureCloudDirectory = (cloudPath: string) => {
89
- if (!existsSync(cloudPath)) {
90
- console.log(chalk.blue('🔧 Creating cloud directory...'))
91
- try {
92
- mkdirSync(cloudPath, { recursive: true })
93
- console.log(chalk.green(`✅ Cloud directory created: ${cloudPath}`))
94
- } catch (error) {
95
- console.log(chalk.red('❌ Failed to create cloud directory:'), error.message)
96
- throw error
97
- }
98
- } else {
99
- console.log(chalk.gray(`ℹ️ Cloud directory already exists: ${cloudPath}`))
100
- }
101
- }
102
-
103
-
104
- const installSystemdService = (serviceContent: string) => {
105
- const servicePath = '/etc/systemd/system/nulljs.service'
106
-
107
- console.log(chalk.blue('🔧 Installing systemd service...'))
108
-
109
- // Write service file
110
- writeFileSync('/tmp/nulljs.service', serviceContent)
111
- execSync(`sudo mv /tmp/nulljs.service ${servicePath}`, { stdio: 'inherit' })
112
-
113
- // Reload systemd and enable service
114
- execSync('sudo systemctl daemon-reload', { stdio: 'inherit' })
115
- execSync('sudo systemctl enable nulljs.service', { stdio: 'inherit' })
116
-
117
- console.log(chalk.green('✅ Systemd service installed and enabled'))
118
- }
119
-
120
- const validateLinux = () => {
121
- if (process.platform !== 'linux') {
122
- console.log(chalk.red('❌ This command only works on Linux'))
123
- process.exit(1)
124
- }
125
- }
126
-
127
- const validateServerBinary = (serverBinPath: string) => {
128
- if (!existsSync(serverBinPath)) {
129
- console.log(chalk.red('❌ Server binary not found at:'), serverBinPath)
130
- console.log(chalk.yellow(' Make sure you have built the server first'))
131
- process.exit(1)
132
- }
133
- }
134
-
135
- const checkExistingProductionConfig = (cloudPath: string): ProductionConfig | null => {
136
- const configPath = join(cloudPath, 'config.json')
137
-
138
- if (!existsSync(configPath)) {
139
- return null
140
- }
141
-
142
- try {
143
- const configContent = JSON.parse(readFileSync(configPath, 'utf8'))
144
- if (configContent.key?.private && configContent.key?.public) {
145
- return configContent as ProductionConfig
146
- }
147
- } catch {
148
- console.log(chalk.yellow('⚠️ Existing production config is invalid, will regenerate'))
149
- }
150
-
151
- return null
152
- }
153
-
154
- const unhost = async (options: { keepData?: boolean } = {}) => {
155
- validateLinux()
156
-
157
- console.log(chalk.blue('🧹 Removing NullJS production hosting...'))
158
-
159
- try {
160
- // Stop and disable the systemd service
161
- console.log(chalk.blue('🛑 Stopping NullJS service...'))
162
- try {
163
- execSync('sudo systemctl stop nulljs', { stdio: 'inherit' })
164
- console.log(chalk.green('✅ Service stopped'))
165
- } catch {
166
- console.log(chalk.yellow('⚠️ Service was not running'))
167
- }
168
-
169
- try {
170
- execSync('sudo systemctl disable nulljs', { stdio: 'inherit' })
171
- console.log(chalk.green('✅ Service disabled'))
172
- } catch {
173
- console.log(chalk.yellow('⚠️ Service was not enabled'))
174
- }
175
-
176
- // Remove the systemd service file
177
- const servicePath = '/etc/systemd/system/nulljs.service'
178
- if (existsSync(servicePath)) {
179
- console.log(chalk.blue('🗑️ Removing systemd service file...'))
180
- execSync(`sudo rm ${servicePath}`, { stdio: 'inherit' })
181
- execSync('sudo systemctl daemon-reload', { stdio: 'inherit' })
182
- console.log(chalk.green('✅ Systemd service file removed'))
183
- }
184
-
185
- // Remove cloud directory (optional)
186
- if (!options.keepData) {
187
- const defaultCloudPath = join(homedir(), '.nulljs')
188
- if (existsSync(defaultCloudPath)) {
189
- console.log(chalk.blue('🗂️ Removing cloud directory...'))
190
- execSync(`rm -rf ${defaultCloudPath}`, { stdio: 'inherit' })
191
- console.log(chalk.green('✅ Cloud directory removed'))
192
- } else {
193
- console.log(chalk.gray('ℹ️ Cloud directory does not exist'))
194
- }
195
- } else {
196
- console.log(chalk.gray('ℹ️ Keeping cloud data (--keep-data specified)'))
197
- }
198
-
199
- console.log(chalk.green('🎉 NullJS hosting cleanup complete!'))
200
- console.log('')
201
- console.log(chalk.blue('📋 Summary:'))
202
- console.log(chalk.gray(' • Systemd service stopped and removed'))
203
- if (!options.keepData) {
204
- console.log(chalk.gray(' • Cloud directory removed'))
205
- }
206
- } catch (error) {
207
- console.log(chalk.red('❌ Failed to remove hosting setup:'), error.message)
208
- process.exit(1)
209
- }
210
- }
211
-
212
- const hostUpdate = async () => {
213
- validateLinux()
214
-
215
- console.log(chalk.blue('🔄 Updating NullJS server...'))
216
-
217
- // Check if service exists
218
- const serviceExists = existsSync('/etc/systemd/system/nulljs.service')
219
- if (!serviceExists) {
220
- console.log(chalk.red('❌ NullJS service is not installed. Run `nulljs host` first.'))
221
- process.exit(1)
222
- }
223
-
224
- let wasRunning = false
225
-
226
- try {
227
- // Check if service is running
228
- execSync('sudo systemctl is-active nulljs >/dev/null 2>&1')
229
- wasRunning = true
230
- console.log(chalk.blue('🛑 Stopping NullJS service...'))
231
- execSync('sudo systemctl stop nulljs', { stdio: 'inherit' })
232
- console.log(chalk.green('✅ Service stopped'))
233
- } catch {
234
- // Service wasn't running, that's fine
235
- console.log(chalk.gray('ℹ️ Service was not running'))
236
- }
237
-
238
- try {
239
- // Update the binary
240
- await updateServer()
241
-
242
- // Restart service if it was running before
243
- if (wasRunning) {
244
- console.log(chalk.blue('🚀 Starting NullJS service...'))
245
- execSync('sudo systemctl start nulljs', { stdio: 'inherit' })
246
- console.log(chalk.green('✅ Service restarted'))
247
- }
248
-
249
- console.log(chalk.green('🎉 NullJS server update complete!'))
250
- console.log('')
251
- console.log(chalk.blue('📋 Service management commands:'))
252
- console.log(chalk.gray(' Start: '), chalk.white('sudo systemctl start nulljs'))
253
- console.log(chalk.gray(' Stop: '), chalk.white('sudo systemctl stop nulljs'))
254
- console.log(chalk.gray(' Status: '), chalk.white('sudo systemctl status nulljs'))
255
- console.log(chalk.gray(' Logs: '), chalk.white('sudo journalctl -u nulljs -f'))
256
- } catch (error) {
257
- console.log(chalk.red('❌ Failed to update server:'), error.message)
258
-
259
- // Try to restart the service even if update failed
260
- if (wasRunning) {
261
- try {
262
- console.log(chalk.yellow('⚠️ Attempting to restart service with previous binary...'))
263
- execSync('sudo systemctl start nulljs', { stdio: 'inherit' })
264
- console.log(chalk.green('✅ Service restarted with previous binary'))
265
- } catch (restartError) {
266
- console.log(chalk.red('❌ Failed to restart service:'), restartError.message)
267
- }
268
- }
269
-
270
- process.exit(1)
271
- }
272
- }
273
-
274
- const host = async (cloudPath?: string, options: { update?: boolean } = {}) => {
275
- // Handle update flag
276
- if (options.update) {
277
- return hostUpdate()
278
- }
279
-
280
- validateLinux()
281
-
282
- // Use provided cloud path or default to ~/.nulljs
283
- const resolvedCloudPath = cloudPath
284
- ? cloudPath.startsWith('/')
285
- ? cloudPath
286
- : join(process.cwd(), cloudPath)
287
- : join(homedir(), '.nulljs')
288
-
289
- console.log(chalk.blue('🚀 Setting up NullJS production hosting...'))
290
- console.log(chalk.gray(` Cloud path: ${resolvedCloudPath}`))
291
-
292
- const serverBinPath = getServerBinPath()
293
- validateServerBinary(serverBinPath)
294
-
295
- // Get current user
296
- const currentUser = process.env.USER || process.env.USERNAME || 'root'
297
- console.log(chalk.blue(`🔧 Setting up service to run as user: ${currentUser}`))
298
-
299
- // Ensure cloud directory exists
300
- ensureCloudDirectory(resolvedCloudPath)
301
-
302
- // Check for existing production config or generate new keys
303
- let productionConfig = checkExistingProductionConfig(resolvedCloudPath)
304
-
305
- if (!productionConfig) {
306
- const { privateKey, publicKey } = await generateProductionKeys()
307
- saveProductionConfig(resolvedCloudPath, privateKey, publicKey)
308
- productionConfig = { key: { private: privateKey, public: publicKey } }
309
-
310
- console.log(chalk.green('🔑 Production keys generated'))
311
- console.log(chalk.blue('📋 Production Public Key:'))
312
- console.log(chalk.gray(publicKey))
313
- } else {
314
- console.log(chalk.green('🔑 Using existing production keys'))
315
- console.log(chalk.blue('📋 Production Public Key:'))
316
- console.log(chalk.gray(productionConfig.key.public))
317
- }
318
-
319
- // Create and install systemd service
320
- const serviceContent = createSystemdService(
321
- resolvedCloudPath,
322
- productionConfig.key.public,
323
- serverBinPath,
324
- currentUser
325
- )
326
- installSystemdService(serviceContent)
327
-
328
- console.log(chalk.green('🎉 NullJS hosting setup complete!'))
329
- console.log('')
330
- console.log(chalk.blue('📋 Service management commands:'))
331
- console.log(chalk.gray(' Start: '), chalk.white('sudo systemctl start nulljs'))
332
- console.log(chalk.gray(' Stop: '), chalk.white('sudo systemctl stop nulljs'))
333
- console.log(chalk.gray(' Status: '), chalk.white('sudo systemctl status nulljs'))
334
- console.log(chalk.gray(' Logs: '), chalk.white('sudo journalctl -u nulljs -f'))
335
- console.log('')
336
- console.log(chalk.yellow('⚠️ Remember to start the service: sudo systemctl start nulljs'))
337
- }
338
-
339
- export { host, unhost }
@@ -1,8 +0,0 @@
1
- export * from './deploy'
2
- export * from './auth'
3
- export * from './secret'
4
- export * from './api'
5
- export * from './create'
6
- export * from './dev'
7
- export * from './host'
8
- export * from './profile'
@@ -1,189 +0,0 @@
1
- import chalk from 'chalk'
2
- import {
3
- listProfiles,
4
- getActiveProfile,
5
- setActiveProfile,
6
- loadProfile,
7
- saveProfile,
8
- deleteProfile,
9
- profileExists,
10
- loadConfigWithProfile
11
- } from '../lib/config'
12
-
13
- export const listProfilesCommand = () => {
14
- const profiles = listProfiles()
15
- const activeProfile = getActiveProfile()
16
-
17
- if (profiles.length === 0) {
18
- console.log(chalk.yellow('No profiles found.'))
19
- console.log(chalk.gray('Create your first profile with: nulljs profile create <name>'))
20
- return
21
- }
22
-
23
- console.log(chalk.bold('\nProfiles:'))
24
- profiles.forEach((profile) => {
25
- const isActive = profile === activeProfile
26
- const marker = isActive ? chalk.green('●') : chalk.gray('○')
27
- const name = isActive ? chalk.green(profile) : profile
28
- const suffix = isActive ? chalk.green(' (active)') : ''
29
- console.log(` ${marker} ${name}${suffix}`)
30
- })
31
-
32
- if (!activeProfile) {
33
- console.log(
34
- chalk.gray('\nNo active profile set. Switch to a profile with: nulljs profile use <name>')
35
- )
36
- }
37
- }
38
-
39
- export const createProfile = (name: string) => {
40
- if (!name) {
41
- console.error(chalk.red('✗'), 'Profile name is required')
42
- process.exit(1)
43
- }
44
-
45
- if (profileExists(name)) {
46
- console.error(chalk.red('✗'), `Profile '${name}' already exists`)
47
- process.exit(1)
48
- }
49
-
50
- try {
51
- const currentConfig = loadConfigWithProfile()
52
- saveProfile(name, currentConfig)
53
- console.log(chalk.green('✓'), `Profile '${chalk.blue(name)}' created`)
54
- } catch (error) {
55
- console.error(chalk.red('✗'), 'Failed to create profile:', error)
56
- process.exit(1)
57
- }
58
- }
59
-
60
- export const useProfile = (name: string) => {
61
- if (!name) {
62
- console.error(chalk.red('✗'), 'Profile name is required')
63
- process.exit(1)
64
- }
65
-
66
- if (!profileExists(name)) {
67
- console.error(chalk.red('✗'), `Profile '${name}' does not exist`)
68
- process.exit(1)
69
- }
70
-
71
- try {
72
- setActiveProfile(name)
73
- console.log(chalk.green('✓'), `Switched to profile '${chalk.blue(name)}'`)
74
- } catch (error) {
75
- console.error(chalk.red('✗'), 'Failed to switch profile:', error)
76
- process.exit(1)
77
- }
78
- }
79
-
80
- export const showProfile = (name?: string) => {
81
- const profileName = name || getActiveProfile()
82
-
83
- if (!profileName) {
84
- console.error(chalk.red('✗'), 'No active profile and no profile name provided')
85
- process.exit(1)
86
- }
87
-
88
- if (!profileExists(profileName)) {
89
- console.error(chalk.red('✗'), `Profile '${profileName}' does not exist`)
90
- process.exit(1)
91
- }
92
-
93
- try {
94
- const config = loadProfile(profileName)
95
- const isActive = profileName === getActiveProfile()
96
-
97
- console.log(chalk.bold(`\nProfile: ${profileName}`), isActive ? chalk.green('(active)') : '')
98
- console.log(chalk.gray('─'.repeat(40)))
99
-
100
- if (config.api) {
101
- console.log(`${chalk.blue('API URL:')} ${config.api}`)
102
- } else {
103
- console.log(`${chalk.blue('API URL:')} ${chalk.gray('(not set)')}`)
104
- }
105
-
106
- if (config.key?.public) {
107
- console.log(`${chalk.blue('Public Key:')} ${config.key.public.substring(0, 20)}...`)
108
- } else {
109
- console.log(`${chalk.blue('Public Key:')} ${chalk.gray('(not set)')}`)
110
- }
111
-
112
- if (config.key?.private) {
113
- console.log(`${chalk.blue('Private Key:')} ${chalk.gray('(set)')}`)
114
- } else {
115
- console.log(`${chalk.blue('Private Key:')} ${chalk.gray('(not set)')}`)
116
- }
117
-
118
- if (config.dev) {
119
- console.log(`${chalk.blue('Dev API Port:')} ${config.dev.apiPort || 3000}`)
120
- console.log(`${chalk.blue('Dev Gateway Port:')} ${config.dev.gatewayPort || 3001}`)
121
- }
122
- } catch (error) {
123
- console.error(chalk.red('✗'), 'Failed to load profile:', error)
124
- process.exit(1)
125
- }
126
- }
127
-
128
- export const removeProfile = (name: string) => {
129
- if (!name) {
130
- console.error(chalk.red('✗'), 'Profile name is required')
131
- process.exit(1)
132
- }
133
-
134
- if (!profileExists(name)) {
135
- console.error(chalk.red('✗'), `Profile '${name}' does not exist`)
136
- process.exit(1)
137
- }
138
-
139
- const activeProfile = getActiveProfile()
140
- if (activeProfile === name) {
141
- console.log(chalk.yellow('⚠'), `Profile '${name}' is currently active`)
142
- }
143
-
144
- try {
145
- const deleted = deleteProfile(name)
146
- if (deleted) {
147
- console.log(chalk.green('✓'), `Profile '${chalk.blue(name)}' removed`)
148
- if (activeProfile === name) {
149
- console.log(chalk.gray('Active profile cleared'))
150
- }
151
- } else {
152
- console.error(chalk.red('✗'), `Failed to remove profile '${name}'`)
153
- process.exit(1)
154
- }
155
- } catch (error) {
156
- console.error(chalk.red('✗'), 'Failed to remove profile:', error)
157
- process.exit(1)
158
- }
159
- }
160
-
161
- export const copyProfile = (fromName: string, toName: string) => {
162
- if (!fromName || !toName) {
163
- console.error(chalk.red('✗'), 'Both source and destination profile names are required')
164
- process.exit(1)
165
- }
166
-
167
- if (!profileExists(fromName)) {
168
- console.error(chalk.red('✗'), `Source profile '${fromName}' does not exist`)
169
- process.exit(1)
170
- }
171
-
172
- if (profileExists(toName)) {
173
- console.error(chalk.red('✗'), `Destination profile '${toName}' already exists`)
174
- process.exit(1)
175
- }
176
-
177
- try {
178
- const sourceConfig = loadProfile(fromName)
179
- saveProfile(toName, sourceConfig)
180
- console.log(
181
- chalk.green('✓'),
182
- `Profile '${chalk.blue(fromName)}' copied to '${chalk.blue(toName)}'`
183
- )
184
- } catch (error) {
185
- console.error(chalk.red('✗'), 'Failed to copy profile:', error)
186
- process.exit(1)
187
- }
188
- }
189
-
@@ -1,79 +0,0 @@
1
- import chalk from 'chalk'
2
- import fs from 'fs/promises'
3
- import path, { resolve } from 'path'
4
-
5
- import { fetchSecretKeys, postSecret } from '../lib/api'
6
-
7
- export const createSecret = async (props: { key: string; value: string }) => {
8
- try {
9
- await postSecret(props)
10
- console.log(chalk.green('Secret stored: ') + chalk.bgGreen.black(props.key))
11
- } catch (error) {
12
- console.log(error)
13
- }
14
- }
15
-
16
- export const listSecretKeys = async () => {
17
- const keys = await fetchSecretKeys()
18
-
19
- if (keys.length === 0) {
20
- console.log(chalk.yellow('No secrets found'))
21
- return
22
- }
23
-
24
- console.log(chalk.bold.blue('Available secret keys:'))
25
- keys.forEach((key, index) => {
26
- console.log(chalk.green(`${index + 1}.`), chalk.cyan(key))
27
- })
28
- }
29
-
30
- export const createSecretsFromFile = async (props: {
31
- filePath: string
32
- log?: (message: string) => void
33
- }) => {
34
- const logger = props.log || console.log
35
-
36
- try {
37
- const file = resolve(props.filePath)
38
- const fileContent = await fs.readFile(file, 'utf-8')
39
- const lines = fileContent.split('\n')
40
-
41
- let createdCount = 0
42
-
43
- for (const line of lines) {
44
- const trimmedLine = line.trim()
45
-
46
- if (!trimmedLine || trimmedLine.startsWith('#')) {
47
- continue
48
- }
49
-
50
- const equalIndex = trimmedLine.indexOf('=')
51
- if (equalIndex === -1) {
52
- logger(chalk.yellow(`Skipping invalid line: ${trimmedLine}`))
53
- continue
54
- }
55
-
56
- const key = trimmedLine.substring(0, equalIndex).trim()
57
- const value = trimmedLine.substring(equalIndex + 1).trim()
58
-
59
- if (!key) {
60
- logger(chalk.yellow(`Skipping line with empty key: ${trimmedLine}`))
61
- continue
62
- }
63
-
64
- try {
65
- await postSecret({ key, value })
66
- logger(chalk.green(`✓ Created secret: ${key}`))
67
- createdCount++
68
- } catch (error) {
69
- logger(chalk.red(`✗ Failed to create secret ${key}:`, error))
70
- }
71
- }
72
-
73
- logger(
74
- chalk.bold.blue(`\nCreated ${createdCount} secrets from ${path.basename(props.filePath)}`)
75
- )
76
- } catch (error) {
77
- logger(chalk.red(`Error reading file ${props.filePath}:`, error))
78
- }
79
- }