@tothalex/nulljs 0.0.47 → 0.0.53

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 (58) hide show
  1. package/package.json +22 -32
  2. package/src/cli.ts +24 -0
  3. package/src/commands/config.ts +130 -0
  4. package/src/commands/deploy.ts +182 -123
  5. package/src/commands/dev.ts +10 -0
  6. package/src/commands/host.ts +130 -139
  7. package/src/commands/index.ts +6 -8
  8. package/src/commands/secret.ts +364 -56
  9. package/src/commands/status.ts +41 -0
  10. package/src/components/DeployAnimation.tsx +92 -0
  11. package/src/components/DeploymentLogsPane.tsx +79 -0
  12. package/src/components/Header.tsx +57 -0
  13. package/src/components/HelpModal.tsx +64 -0
  14. package/src/components/SystemLogsPane.tsx +78 -0
  15. package/src/config/index.ts +181 -0
  16. package/src/lib/bundle/function.ts +125 -0
  17. package/src/lib/bundle/index.ts +3 -0
  18. package/src/lib/bundle/react.ts +149 -0
  19. package/src/lib/deploy.ts +103 -0
  20. package/src/lib/server.ts +160 -0
  21. package/src/lib/vite.ts +120 -0
  22. package/src/lib/watcher.ts +274 -0
  23. package/src/ui.tsx +363 -0
  24. package/tsconfig.json +30 -0
  25. package/scripts/install-server.js +0 -199
  26. package/src/commands/api.ts +0 -16
  27. package/src/commands/auth.ts +0 -54
  28. package/src/commands/create.ts +0 -43
  29. package/src/commands/dev/function/index.ts +0 -221
  30. package/src/commands/dev/function/utils.ts +0 -99
  31. package/src/commands/dev/index.tsx +0 -126
  32. package/src/commands/dev/logging-manager.ts +0 -87
  33. package/src/commands/dev/server/index.ts +0 -48
  34. package/src/commands/dev/server/utils.ts +0 -37
  35. package/src/commands/dev/ui/components/scroll-area.tsx +0 -141
  36. package/src/commands/dev/ui/components/tab-bar.tsx +0 -67
  37. package/src/commands/dev/ui/index.tsx +0 -71
  38. package/src/commands/dev/ui/logging-context.tsx +0 -76
  39. package/src/commands/dev/ui/tabs/functions-tab.tsx +0 -35
  40. package/src/commands/dev/ui/tabs/server-tab.tsx +0 -36
  41. package/src/commands/dev/ui/tabs/vite-tab.tsx +0 -35
  42. package/src/commands/dev/ui/use-logging.tsx +0 -34
  43. package/src/commands/dev/vite/index.ts +0 -54
  44. package/src/commands/dev/vite/utils.ts +0 -71
  45. package/src/commands/profile.ts +0 -189
  46. package/src/index.ts +0 -346
  47. package/src/lib/api.ts +0 -189
  48. package/src/lib/bundle/function/index.ts +0 -46
  49. package/src/lib/bundle/react/index.ts +0 -2
  50. package/src/lib/bundle/react/spa.ts +0 -77
  51. package/src/lib/bundle/react/ssr/client.ts +0 -93
  52. package/src/lib/bundle/react/ssr/config.ts +0 -77
  53. package/src/lib/bundle/react/ssr/index.ts +0 -4
  54. package/src/lib/bundle/react/ssr/props.ts +0 -71
  55. package/src/lib/bundle/react/ssr/server.ts +0 -83
  56. package/src/lib/config.ts +0 -347
  57. package/src/lib/deployment.ts +0 -244
  58. package/src/lib/update-server.ts +0 -262
@@ -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
-
package/src/index.ts DELETED
@@ -1,346 +0,0 @@
1
- #! /usr/bin/env bun
2
-
3
- import yargs from 'yargs'
4
- import { hideBin } from 'yargs/helpers'
5
-
6
- import {
7
- deploy,
8
- auth,
9
- createSecret,
10
- listSecretKeys,
11
- setApiUrl,
12
- create,
13
- createSecretsFromFile,
14
- dev,
15
- host,
16
- unhost,
17
- listProfilesCommand,
18
- createProfile,
19
- useProfile,
20
- showProfile,
21
- removeProfile,
22
- copyProfile
23
- } from './commands'
24
- import chalk from 'chalk'
25
- import { getActiveProfile, listProfiles, profileExists, loadProfile } from './lib/config'
26
-
27
- const showWelcome = () => {
28
- console.log(chalk.bold.blue('\n🚀 NullJS CLI'))
29
- console.log(chalk.gray('─'.repeat(40)))
30
-
31
- // Show current profile
32
- const activeProfile = getActiveProfile()
33
- if (activeProfile && profileExists(activeProfile)) {
34
- const config = loadProfile(activeProfile)
35
- console.log(chalk.bold(`\n📋 Current Profile: ${chalk.green(activeProfile)}`))
36
-
37
- if (config.api) {
38
- console.log(` ${chalk.blue('API URL:')} ${config.api}`)
39
- } else {
40
- console.log(` ${chalk.blue('API URL:')} ${chalk.red('(not configured)')}`)
41
- }
42
-
43
- if (config.key?.public && config.key?.private) {
44
- console.log(` ${chalk.blue('Authentication:')} ${chalk.green('✓ configured')}`)
45
- } else {
46
- console.log(` ${chalk.blue('Authentication:')} ${chalk.red('✗ not configured')}`)
47
- }
48
- } else {
49
- console.log(chalk.yellow('\n⚠️ No active profile selected'))
50
- const profiles = listProfiles()
51
- if (profiles.length > 0) {
52
- console.log(chalk.gray(' Available profiles:'))
53
- profiles.forEach((profile) => console.log(chalk.gray(` - ${profile}`)))
54
- console.log(chalk.gray(' Switch to a profile: nulljs profile use <name>'))
55
- } else {
56
- console.log(chalk.gray(' Create your first profile: nulljs profile create <name>'))
57
- }
58
- }
59
-
60
- // Show available commands
61
- console.log(chalk.bold('\n📚 Available Commands:'))
62
- console.log(chalk.blue(' nulljs create <name>') + chalk.gray(' Create a new project'))
63
- console.log(chalk.blue(' nulljs deploy [path]') + chalk.gray(' Deploy your project'))
64
- console.log(chalk.blue(' nulljs dev [path]') + chalk.gray(' Start development mode'))
65
- console.log(
66
- chalk.blue(' nulljs auth') + chalk.gray(' Generate authentication keys')
67
- )
68
- console.log(chalk.blue(' nulljs config set-api <url>') + chalk.gray(' Set API URL'))
69
- console.log(chalk.blue(' nulljs secret <action>') + chalk.gray(' Manage secrets'))
70
- console.log(chalk.blue(' nulljs profile <action>') + chalk.gray(' Manage profiles'))
71
- console.log(
72
- chalk.blue(' nulljs host [cloud-path]') + chalk.gray(' Set up production hosting')
73
- )
74
- console.log(
75
- chalk.blue(' nulljs host --update') + chalk.gray(' Update server binary and restart service')
76
- )
77
- console.log(chalk.blue(' nulljs unhost') + chalk.gray(' Remove production hosting'))
78
-
79
- console.log(chalk.gray('\n💡 Quick Start:'))
80
- if (!activeProfile) {
81
- console.log(chalk.gray(' 1. nulljs profile create my-profile'))
82
- console.log(chalk.gray(' 2. nulljs auth'))
83
- console.log(chalk.gray(' 3. nulljs config set-api <your-api-url>'))
84
- console.log(chalk.gray(' 4. nulljs create my-project'))
85
- } else {
86
- console.log(chalk.gray(' • nulljs create my-project (create a new project)'))
87
- console.log(chalk.gray(' • nulljs dev (start development)'))
88
- console.log(chalk.gray(' • nulljs deploy (deploy to production)'))
89
- }
90
-
91
- console.log(chalk.gray('\n Run "nulljs --help" for detailed usage\n'))
92
- }
93
-
94
- const parser = yargs(hideBin(process.argv))
95
- .scriptName('nulljs')
96
- .usage('Usage: $0 <command> [options]')
97
- .command(
98
- 'create <name>',
99
- 'Create a nulljs project with <name>',
100
- (yargs) =>
101
- yargs.positional('name', {
102
- description: 'Project name',
103
- type: 'string',
104
- demandOption: true
105
- }),
106
- (argv) => create(argv.name)
107
- )
108
- .command(
109
- 'deploy [path]',
110
- 'Deploy a project to the platform',
111
- (yargs) =>
112
- yargs.positional('path', {
113
- description:
114
- 'Path to the project directory or file (optional, defaults to current directory)',
115
- type: 'string',
116
- demandOption: false
117
- }),
118
- (argv) => deploy(argv.path)
119
- )
120
- .command(
121
- 'dev [path]',
122
- 'Start dev mode with Vite server and function watching',
123
- (yargs) =>
124
- yargs.positional('path', {
125
- description: 'Path to the src directory (defaults to ./src)',
126
- type: 'string',
127
- default: './src'
128
- }),
129
- (argv) => dev(argv.path)
130
- )
131
- .command(
132
- 'host [cloud-path]',
133
- 'Set up production hosting with systemd service (Linux only)',
134
- (yargs) =>
135
- yargs
136
- .positional('cloud-path', {
137
- description: 'Path to cloud data directory (defaults to ~/.nulljs)',
138
- type: 'string',
139
- demandOption: false
140
- })
141
- .option('update', {
142
- description: 'Update the server binary to the latest version and restart the service',
143
- type: 'boolean',
144
- default: false
145
- }),
146
- (argv) => host(argv['cloud-path'], { update: argv.update })
147
- )
148
- .command(
149
- 'unhost',
150
- 'Remove production hosting setup (Linux only)',
151
- (yargs) =>
152
- yargs.option('keep-data', {
153
- description: 'Keep the cloud data directory',
154
- type: 'boolean',
155
- default: false
156
- }),
157
- (argv) => unhost({ keepData: argv['keep-data'] })
158
- )
159
- .command(
160
- 'auth',
161
- 'Generate or regenerate authentication keys',
162
- (yargs) =>
163
- yargs.option('profile', {
164
- description: 'Save keys to a specific profile',
165
- type: 'string',
166
- demandOption: false
167
- }),
168
- (argv) => auth(argv.profile)
169
- )
170
- .command(
171
- 'config',
172
- 'Configuration management',
173
- (yargs) =>
174
- yargs
175
- .command(
176
- 'set-api <url>',
177
- 'Set the API URL for the platform',
178
- (yargs) =>
179
- yargs
180
- .positional('url', {
181
- description: 'API URL to save in configuration',
182
- type: 'string',
183
- demandOption: true
184
- })
185
- .option('profile', {
186
- description: 'Save to a specific profile',
187
- type: 'string',
188
- demandOption: false
189
- }),
190
- (argv) => setApiUrl(argv.url, argv.profile)
191
- )
192
- .demandCommand(1, 'You need to specify a config action'),
193
- () => {}
194
- )
195
- .command(
196
- 'secret <action>',
197
- 'Secret management operations',
198
- (yargs) =>
199
- yargs
200
- .command(
201
- 'create',
202
- 'Create a new secret',
203
- (yargs) =>
204
- yargs
205
- .option('key', {
206
- description: 'Key name for the secret',
207
- type: 'string',
208
- demandOption: false
209
- })
210
- .option('value', {
211
- description: 'Value for the secret',
212
- type: 'string',
213
- demandOption: false
214
- })
215
- .option('file', {
216
- description: 'Path to file containing the secret value',
217
- type: 'string',
218
- demandOption: false
219
- })
220
- .check((argv) => {
221
- // Either file is provided OR both key and value are provided
222
- if (argv.file && (argv.key || argv.value)) {
223
- throw new Error('Cannot use --file with --key or --value options')
224
- }
225
- if (!argv.file && (!argv.key || !argv.value)) {
226
- throw new Error('Must provide either --file OR both --key and --value')
227
- }
228
- return true
229
- }),
230
- (argv) => {
231
- if (argv.file) {
232
- createSecretsFromFile({
233
- filePath: argv.file
234
- })
235
- } else {
236
- createSecret({ key: argv.key!, value: argv.value! })
237
- }
238
- }
239
- )
240
- .command('list', 'List all available secret keys', {}, () => listSecretKeys())
241
- .demandCommand(1, 'You need to specify a secret action'),
242
- () => {}
243
- )
244
- .command(
245
- 'profile <action>',
246
- 'Profile management operations',
247
- (yargs) =>
248
- yargs
249
- .command('list', 'List all available profiles', {}, () => listProfilesCommand())
250
- .command(
251
- 'create <name>',
252
- 'Create a new profile',
253
- (yargs) =>
254
- yargs.positional('name', {
255
- description: 'Profile name',
256
- type: 'string',
257
- demandOption: true
258
- }),
259
- (argv) => createProfile(argv.name)
260
- )
261
- .command(
262
- 'use <name>',
263
- 'Switch to a profile',
264
- (yargs) =>
265
- yargs.positional('name', {
266
- description: 'Profile name to switch to',
267
- type: 'string',
268
- demandOption: true
269
- }),
270
- (argv) => useProfile(argv.name)
271
- )
272
- .command(
273
- 'show [name]',
274
- 'Show profile configuration',
275
- (yargs) =>
276
- yargs.positional('name', {
277
- description: 'Profile name (defaults to active profile)',
278
- type: 'string',
279
- demandOption: false
280
- }),
281
- (argv) => showProfile(argv.name)
282
- )
283
- .command(
284
- 'remove <name>',
285
- 'Remove a profile',
286
- (yargs) =>
287
- yargs.positional('name', {
288
- description: 'Profile name to remove',
289
- type: 'string',
290
- demandOption: true
291
- }),
292
- (argv) => removeProfile(argv.name)
293
- )
294
- .command(
295
- 'copy <from> <to>',
296
- 'Copy a profile to a new profile',
297
- (yargs) =>
298
- yargs
299
- .positional('from', {
300
- description: 'Source profile name',
301
- type: 'string',
302
- demandOption: true
303
- })
304
- .positional('to', {
305
- description: 'Destination profile name',
306
- type: 'string',
307
- demandOption: true
308
- }),
309
- (argv) => copyProfile(argv.from, argv.to)
310
- )
311
- .demandCommand(1, 'You need to specify a profile action'),
312
- () => {}
313
- )
314
- .help('h')
315
- .alias('h', 'help')
316
- .version('0.0.3')
317
- .alias('v', 'version')
318
- .example('$0 create my-project', 'Create project called my-project')
319
- .example('$0 deploy ./my-project', 'Deploy a project from the current directory')
320
- .example('$0 dev', 'Start dev mode for current project (./src)')
321
- .example('$0 dev ./src', 'Start dev mode for specific src directory')
322
- .example('$0 host', 'Set up production hosting with default cloud path (~/.nulljs)')
323
- .example('$0 host /var/nulljs', 'Set up production hosting with custom cloud path')
324
- .example('$0 host --update', 'Update server binary to latest version and restart service')
325
- .example('$0 unhost', 'Remove production hosting (removes service and data)')
326
- .example('$0 unhost --keep-data', 'Remove hosting but keep cloud data')
327
- .example('$0 auth', 'Generate authentication keys')
328
- .example('$0 config set-api https://api.example.com', 'Set the API URL')
329
- .example('$0 secret create --key MY_KEY --value "secret value"', 'Create a new secret')
330
- .example('$0 secret create --file secrets.json', 'Create secrets from a file')
331
- .example('$0 profile list', 'List all available profiles')
332
- .example('$0 profile create development', 'Create a new profile called development')
333
- .example('$0 profile use production', 'Switch to the production profile')
334
- .example('$0 profile show', 'Show the current active profile configuration')
335
- .example('$0 profile copy development staging', 'Copy development profile to staging')
336
- .epilogue('For more information, visit: https://your-docs-url.com')
337
-
338
- // Parse arguments and show welcome screen if no command is provided
339
- async function main() {
340
- const argv = await parser.parse()
341
- if (argv._.length === 0) {
342
- showWelcome()
343
- }
344
- }
345
-
346
- main().catch(console.error)