@tothalex/nulljs 0.0.48 → 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,262 +0,0 @@
1
- import { existsSync, createWriteStream, chmodSync, unlinkSync, mkdirSync } from 'node:fs'
2
- import { join, dirname } from 'node:path'
3
- import { fileURLToPath } from 'node:url'
4
- import https from 'node:https'
5
- import * as tar from 'tar'
6
- import chalk from 'chalk'
7
-
8
- // --- Configuration ---
9
- const S3_BASE_URL = 'https://nulljs.s3.eu-north-1.amazonaws.com'
10
- const S3_PREFIX = 'releases/'
11
- const DOWNLOAD_BASE_URL = `${S3_BASE_URL}/${S3_PREFIX}`
12
- // ---------------------
13
-
14
- interface PlatformInfo {
15
- target: string
16
- extension: string
17
- binaryName: string
18
- }
19
-
20
- interface S3DownloadInfo {
21
- downloadUrl: string
22
- version: string
23
- }
24
-
25
- // --- Core Helper Functions (Unchanged) ---
26
-
27
- function getPlatformInfo(): PlatformInfo {
28
- const platform = process.platform
29
- const arch = process.arch
30
-
31
- const platformMap: Record<string, Record<string, string>> = {
32
- linux: {
33
- x64: 'x86_64-unknown-linux-gnu',
34
- arm64: 'aarch64-unknown-linux-gnu'
35
- },
36
- darwin: {
37
- x64: 'x86_64-apple-darwin',
38
- arm64: 'aarch64-apple-darwin'
39
- }
40
- }
41
-
42
- const target = platformMap[platform]?.[arch]
43
- if (!target) {
44
- throw new Error(`Unsupported platform: ${platform}-${arch}`)
45
- }
46
-
47
- const extension = '.tar.gz'
48
- const binaryName = 'server'
49
-
50
- return { target, extension, binaryName }
51
- }
52
-
53
- async function downloadFile(url: string, destination: string): Promise<void> {
54
- return new Promise((resolve, reject) => {
55
- const file = createWriteStream(destination)
56
-
57
- https
58
- .get(url, (response) => {
59
- if (response.statusCode === 302 || response.statusCode === 301) {
60
- // Handle redirect
61
- return downloadFile(response.headers.location!, destination).then(resolve).catch(reject)
62
- }
63
-
64
- if (response.statusCode !== 200) {
65
- reject(new Error(`Failed to download: ${response.statusCode}`))
66
- return
67
- }
68
-
69
- response.pipe(file)
70
-
71
- file.on('finish', () => {
72
- file.close()
73
- resolve()
74
- })
75
-
76
- file.on('error', reject)
77
- })
78
- .on('error', reject)
79
- })
80
- }
81
-
82
- async function extractArchive(
83
- archivePath: string,
84
- extractPath: string,
85
- binaryName: string
86
- ): Promise<void> {
87
- // Extract tar.gz
88
- await tar.x({
89
- file: archivePath,
90
- cwd: extractPath
91
- })
92
-
93
- // Make binary executable
94
- const binaryPath = join(extractPath, binaryName)
95
- chmodSync(binaryPath, '755')
96
- }
97
-
98
- function getServerBinPath(): string {
99
- // Try to find the server binary relative to this module
100
- const currentFile = fileURLToPath(import.meta.url)
101
- const moduleRoot = join(dirname(currentFile), '../..')
102
- return join(moduleRoot, 'bin', 'server')
103
- }
104
-
105
- // --- S3 LISTING Functions (New) ---
106
-
107
- /**
108
- * Fetches the raw XML listing from S3.
109
- */
110
- async function fetchXml(url: string): Promise<string> {
111
- return new Promise((resolve, reject) => {
112
- https
113
- .get(url, (res) => {
114
- if (res.statusCode !== 200) {
115
- // This likely indicates a 403 Access Denied error
116
- reject(
117
- new Error(`S3 Request Failed (${res.statusCode}): Check public 's3:ListBucket' policy.`)
118
- )
119
- return
120
- }
121
- let data = ''
122
- res.on('data', (chunk) => (data += chunk))
123
- res.on('end', () => resolve(data))
124
- })
125
- .on('error', reject)
126
- })
127
- }
128
-
129
- /**
130
- * Lists the S3 prefix, parses the XML, and determines the latest version tag.
131
- */
132
- async function getLatestVersionFromS3(target: string, extension: string): Promise<S3DownloadInfo> {
133
- // Query S3 for folders using delimiter and prefix
134
- const listUrl = `${S3_BASE_URL}/?delimiter=/&prefix=${S3_PREFIX}`
135
- const xmlData = await fetchXml(listUrl)
136
-
137
- // Regex to find all CommonPrefixes entries (the version folders)
138
- // Example: <Prefix>releases/v1.0.0/</Prefix>
139
- const prefixRegex = /<Prefix>(releases\/v[^<]+)\/<\/Prefix>/g
140
- const versionFolders: string[] = []
141
- let match: RegExpExecArray | null
142
-
143
- while ((match = prefixRegex.exec(xmlData)) !== null) {
144
- // Extract version part: "releases/v1.0.0/" -> "v1.0.0"
145
- const fullPrefix = match[1]
146
- const version = fullPrefix.substring(S3_PREFIX.length)
147
- versionFolders.push(version)
148
- }
149
-
150
- if (versionFolders.length === 0) {
151
- throw new Error('No version folders found in S3 bucket. Has the CI/CD run?')
152
- }
153
-
154
- // Sort versions to find the latest (using semantic versioning logic)
155
- const sortedVersions = versionFolders.sort((a, b) => {
156
- // Strips 'v', splits by '.', and converts to number arrays for comparison
157
- const aParts = a.replace('v', '').split('.').map(Number)
158
- const bParts = b.replace('v', '').split('.').map(Number)
159
-
160
- // Compare major, minor, and patch numbers (assuming vX.Y.Z)
161
- for (let i = 0; i < 3; i++) {
162
- if (aParts[i] > bParts[i]) return 1
163
- if (aParts[i] < bParts[i]) return -1
164
- }
165
- return 0
166
- })
167
-
168
- // The latest version is the last one after sorting
169
- const latestVersion = sortedVersions[sortedVersions.length - 1]
170
-
171
- // Construct the full download URL
172
- const downloadUrl = `${DOWNLOAD_BASE_URL}${latestVersion}/nulljs-server-${target}${extension}`
173
-
174
- return { downloadUrl, version: latestVersion }
175
- }
176
-
177
- // --- Main Update Function (Modified) ---
178
-
179
- export async function updateServer(): Promise<void> {
180
- try {
181
- console.log(chalk.blue('🔄 Updating nulljs server binary...'))
182
-
183
- const { target, extension, binaryName } = getPlatformInfo()
184
-
185
- const serverBinPath = getServerBinPath()
186
- const binDir = dirname(serverBinPath)
187
- const archivePath = join(binDir, `server${extension}`)
188
- const backupPath = join(binDir, 'server.backup')
189
-
190
- // Create bin directory if it doesn't exist
191
- if (!existsSync(binDir)) {
192
- mkdirSync(binDir, { recursive: true })
193
- }
194
-
195
- // Backup existing binary if it exists
196
- if (existsSync(serverBinPath)) {
197
- console.log(chalk.blue('💾 Backing up existing binary...'))
198
-
199
- if (existsSync(backupPath)) {
200
- unlinkSync(backupPath)
201
- }
202
-
203
- const fs = await import('node:fs/promises')
204
- await fs.copyFile(serverBinPath, backupPath)
205
- console.log(chalk.green('✅ Backup created'))
206
- }
207
-
208
- console.log(chalk.blue(`🔍 Searching for latest server version...`))
209
-
210
- // 1. Get download URL and version from S3 listing (NEW LOGIC)
211
- const { downloadUrl, version } = await getLatestVersionFromS3(target, extension)
212
- console.log(chalk.blue(` Found latest version: ${version} for ${target}`))
213
- console.log(chalk.blue(` Downloading from: ${downloadUrl}`))
214
-
215
- try {
216
- // Download the archive
217
- await downloadFile(downloadUrl, archivePath)
218
- console.log(chalk.green('✅ Download completed'))
219
-
220
- // Remove existing binary before extracting new one
221
- if (existsSync(serverBinPath)) {
222
- unlinkSync(serverBinPath)
223
- }
224
-
225
- // Extract the binary
226
- console.log(chalk.blue('📂 Extracting binary...'))
227
- await extractArchive(archivePath, binDir, binaryName)
228
-
229
- // Clean up archive
230
- unlinkSync(archivePath)
231
-
232
- // Remove backup since update was successful
233
- if (existsSync(backupPath)) {
234
- unlinkSync(backupPath)
235
- }
236
-
237
- console.log(chalk.green('✅ nulljs server updated successfully'))
238
- } catch (error) {
239
- // If update failed and we have a backup, restore it
240
- if (existsSync(backupPath)) {
241
- console.log(chalk.yellow('⚠️ Update failed, restoring backup...'))
242
-
243
- if (existsSync(serverBinPath)) {
244
- unlinkSync(serverBinPath)
245
- }
246
-
247
- const fs = await import('node:fs/promises')
248
- await fs.copyFile(backupPath, serverBinPath)
249
- unlinkSync(backupPath)
250
-
251
- console.log(chalk.green('✅ Backup restored'))
252
- }
253
-
254
- throw error
255
- }
256
- } catch (error) {
257
- // Ensure the error message is available if it's not a standard Error object
258
- const errorMessage = error instanceof Error ? error.message : String(error)
259
- console.error(chalk.red('❌ Failed to update server binary:'), errorMessage)
260
- throw error
261
- }
262
- }