rajt 0.0.74 → 0.0.75
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.
- package/package.json +1 -1
- package/src/cli/commands/dev.ts +117 -112
- package/src/cli/commands/utils.ts +3 -3
- package/src/utils/log.ts +5 -0
package/package.json
CHANGED
package/src/cli/commands/dev.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { spawn, type ChildProcess } from 'node:child_process'
|
|
|
4
4
|
import { defineCommand } from 'citty'
|
|
5
5
|
import type { Miniflare } from 'miniflare'
|
|
6
6
|
import { _root, build, wait, watch, normalizePlatform, platformError, getRuntime, createMiniflare, getDockerHost } from './utils'
|
|
7
|
-
import {
|
|
7
|
+
import { error, event, log, rn, warn } from '../../utils/log'
|
|
8
8
|
import { withPort } from '../../utils/port'
|
|
9
9
|
import shutdown from '../../utils/shutdown'
|
|
10
10
|
|
|
@@ -39,49 +39,83 @@ export default defineCommand({
|
|
|
39
39
|
|
|
40
40
|
const desiredPort = args.port ? Number(args.port) : 3000
|
|
41
41
|
const host = args.host ? String(args.host) : 'localhost'
|
|
42
|
+
|
|
43
|
+
let isBuilding = false
|
|
44
|
+
const startApp = async (start: Function, stop: Function|undefined = undefined, building: boolean = true) => {
|
|
45
|
+
if (building) {
|
|
46
|
+
if (isBuilding) return
|
|
47
|
+
isBuilding = true
|
|
48
|
+
event('Building..')
|
|
49
|
+
}
|
|
50
|
+
const fn = async () => {
|
|
51
|
+
building && await build(platform)
|
|
52
|
+
await start()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await fn()
|
|
57
|
+
watch(async () => {
|
|
58
|
+
event('Restarting..')
|
|
59
|
+
await fn()
|
|
60
|
+
// event('Restarted...')
|
|
61
|
+
})
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
stop && shutdown(stop)
|
|
64
|
+
} catch (e: any) {
|
|
65
|
+
error(e)
|
|
66
|
+
process.exit(0)
|
|
67
|
+
} finally {
|
|
68
|
+
isBuilding = false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const applyExit = async (app: ChildProcess | null) => {
|
|
73
|
+
if (!app) return null
|
|
74
|
+
|
|
75
|
+
app //?.on('exit', code => process.exit(code ?? 0))
|
|
76
|
+
.on('message', msg => {
|
|
77
|
+
process.send && process.send(msg)
|
|
78
|
+
}).on('disconnect', () => {
|
|
79
|
+
process.disconnect && process.disconnect()
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
const killProcess = async (app: ChildProcess | null) => {
|
|
83
|
+
if (!app) return null
|
|
84
|
+
// event('Stopping..')
|
|
85
|
+
try {
|
|
86
|
+
if (!app?.killed) {
|
|
87
|
+
app.kill('SIGTERM')
|
|
88
|
+
await wait(1000)
|
|
89
|
+
|
|
90
|
+
if (!app?.killed) { // force kill
|
|
91
|
+
app.kill('SIGKILL')
|
|
92
|
+
await wait(1000)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null
|
|
97
|
+
} catch (e) {
|
|
98
|
+
error('Error stopping:', e)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const started = (port: number) => {
|
|
105
|
+
log(`Starting API on http://${host}:${port}`)
|
|
106
|
+
rn()
|
|
107
|
+
}
|
|
108
|
+
|
|
42
109
|
switch (platform) {
|
|
43
110
|
case 'aws':
|
|
44
111
|
return withPort(desiredPort, async (port) => {
|
|
45
|
-
|
|
112
|
+
started(port)
|
|
46
113
|
let lambda: ChildProcess | null = null
|
|
47
|
-
|
|
48
|
-
const buildLambda = async () => {
|
|
49
|
-
if (isBuilding) return
|
|
50
|
-
isBuilding = true
|
|
51
|
-
step('Building lambda')
|
|
52
|
-
try {
|
|
53
|
-
await build(platform)
|
|
54
|
-
if (!lambda) await startLambda()
|
|
55
|
-
} catch (e: any) {
|
|
56
|
-
error('Build failed:', e?.message || e)
|
|
57
|
-
process.exit(0)
|
|
58
|
-
} finally {
|
|
59
|
-
isBuilding = false
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
114
|
const stopLambda = async () => {
|
|
64
|
-
|
|
65
|
-
step('Stopping lambda process...')
|
|
66
|
-
try {
|
|
67
|
-
if (!lambda?.killed) {
|
|
68
|
-
lambda.kill('SIGTERM')
|
|
69
|
-
await wait(1000)
|
|
70
|
-
|
|
71
|
-
if (!lambda?.killed) { // force kill
|
|
72
|
-
lambda.kill('SIGKILL')
|
|
73
|
-
await wait(1000)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
lambda = null
|
|
78
|
-
} catch (e) {
|
|
79
|
-
warn('Error stopping lambda:', e)
|
|
80
|
-
}
|
|
115
|
+
lambda = await killProcess(lambda)
|
|
81
116
|
}
|
|
82
|
-
|
|
83
117
|
const startLambda = async () => {
|
|
84
|
-
await stopLambda()
|
|
118
|
+
if (lambda) await stopLambda()
|
|
85
119
|
|
|
86
120
|
lambda = spawn(
|
|
87
121
|
'sam',
|
|
@@ -97,106 +131,77 @@ export default defineCommand({
|
|
|
97
131
|
shell: process.platform == 'win32',
|
|
98
132
|
env: {...process.env, DOCKER_HOST: getDockerHost()},
|
|
99
133
|
}
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
.on('message', msg => {
|
|
108
|
-
|
|
109
|
-
}).on('disconnect', () => {
|
|
110
|
-
|
|
111
|
-
}).on('error', e => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
})
|
|
115
|
-
|
|
134
|
+
)
|
|
135
|
+
//.on('exit', code => {
|
|
136
|
+
// warn(`Lambda process exited with code ${code ?? 0}`)
|
|
137
|
+
// if (code != 0 && code != null)
|
|
138
|
+
// error('Lambda process crashed, waiting for restart...')
|
|
139
|
+
|
|
140
|
+
// lambda = null
|
|
141
|
+
// }).on('message', msg => {
|
|
142
|
+
// process.send && process.send(msg)
|
|
143
|
+
// }).on('disconnect', () => {
|
|
144
|
+
// process.disconnect && process.disconnect()
|
|
145
|
+
// }).on('error', e => {
|
|
146
|
+
// error('Lambda process error:', e)
|
|
147
|
+
// lambda = null
|
|
148
|
+
// })
|
|
149
|
+
applyExit(lambda)
|
|
116
150
|
await wait(2000)
|
|
117
|
-
|
|
118
|
-
step('Lambda process started successfully')
|
|
119
151
|
}
|
|
120
152
|
|
|
121
|
-
await
|
|
122
|
-
event(`API running on http://${host}:${port}`)
|
|
123
|
-
|
|
124
|
-
watch(async () => {
|
|
125
|
-
await buildLambda()
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
shutdown(async () => {
|
|
129
|
-
await stopLambda()
|
|
130
|
-
})
|
|
153
|
+
await startApp(startLambda, stopLambda)
|
|
131
154
|
})
|
|
132
155
|
case 'cf':
|
|
133
156
|
return withPort(desiredPort, async (port) => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const buildWorker = async () => {
|
|
137
|
-
if (isBuilding) return
|
|
138
|
-
isBuilding = true
|
|
139
|
-
step('Building worker')
|
|
140
|
-
try {
|
|
141
|
-
await build(platform)
|
|
142
|
-
await startWorker()
|
|
143
|
-
} catch (e: any) {
|
|
144
|
-
error('Build failed:', e?.message || e)
|
|
145
|
-
process.exit(0)
|
|
146
|
-
} finally {
|
|
147
|
-
isBuilding = false
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
157
|
+
started(port)
|
|
151
158
|
let worker: Miniflare | null = null
|
|
152
159
|
const startWorker = async () => {
|
|
153
160
|
if (worker) await worker.dispose()
|
|
154
|
-
|
|
155
161
|
worker = await createMiniflare({ port, host, liveReload: false })
|
|
156
162
|
}
|
|
157
163
|
|
|
158
|
-
await
|
|
159
|
-
event(`API running on http://${host}:${port}`)
|
|
160
|
-
|
|
161
|
-
watch(async () => {
|
|
162
|
-
step('Restarting server')
|
|
163
|
-
await buildWorker()
|
|
164
|
-
step('Server restarted')
|
|
165
|
-
})
|
|
164
|
+
await startApp(startWorker)
|
|
166
165
|
})
|
|
167
166
|
default:
|
|
168
167
|
case 'node':
|
|
169
168
|
return withPort(desiredPort, async (port) => {
|
|
169
|
+
started(port)
|
|
170
170
|
const isBun = getRuntime() == 'bun'
|
|
171
171
|
const params = isBun
|
|
172
172
|
? ['run', '--port='+ port, '--hot', '--silent', '--no-clear-screen', '--no-summary', join(_root, 'node_modules/rajt/src/dev.ts')]
|
|
173
173
|
: [join(_root, 'node_modules/.bin/tsx'), 'watch', join(_root, 'node_modules/rajt/src/dev-node.ts')]
|
|
174
174
|
|
|
175
|
-
const child = spawn(
|
|
176
|
-
process.execPath,
|
|
177
|
-
params,
|
|
178
|
-
{
|
|
179
|
-
stdio: ['inherit', isBun ? 'pipe' : 'inherit', 'inherit', 'ipc'],
|
|
180
|
-
env: {...process.env, PORT: port},
|
|
181
|
-
}
|
|
182
|
-
)
|
|
183
175
|
|
|
184
|
-
|
|
176
|
+
let nodeApp: ChildProcess | null = null
|
|
177
|
+
const stopNode = async () => {
|
|
178
|
+
nodeApp = await killProcess(nodeApp)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const startNode = async () => {
|
|
182
|
+
if (nodeApp) await stopNode()
|
|
183
|
+
|
|
184
|
+
nodeApp = spawn(
|
|
185
|
+
process.execPath,
|
|
186
|
+
params,
|
|
187
|
+
{
|
|
188
|
+
stdio: ['inherit', isBun ? 'pipe' : 'inherit', 'inherit', 'ipc'],
|
|
189
|
+
env: {...process.env, PORT: port},
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if (isBun && nodeApp?.stdout) {
|
|
194
|
+
nodeApp.stdout?.on('data', data => {
|
|
195
|
+
const output = data.toString()
|
|
196
|
+
if (!output.includes('Started development server'))
|
|
197
|
+
process.stdout.write(output)
|
|
198
|
+
})
|
|
199
|
+
}
|
|
185
200
|
|
|
186
|
-
|
|
187
|
-
child.stdout?.on('data', data => {
|
|
188
|
-
const output = data.toString()
|
|
189
|
-
if (!output.includes('Started development server'))
|
|
190
|
-
process.stdout.write(output)
|
|
191
|
-
})
|
|
201
|
+
applyExit(nodeApp)
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
|
|
195
|
-
.on('message', msg => {
|
|
196
|
-
process.send && process.send(msg)
|
|
197
|
-
}).on('disconnect', () => {
|
|
198
|
-
process.disconnect && process.disconnect()
|
|
199
|
-
})
|
|
204
|
+
await startApp(startNode, stopNode, false)
|
|
200
205
|
})
|
|
201
206
|
}
|
|
202
207
|
},
|
|
@@ -10,7 +10,7 @@ import { gray } from '../../utils/colors'
|
|
|
10
10
|
import type { ChokidarEventName, Platform } from './types'
|
|
11
11
|
|
|
12
12
|
import { cacheRoutes } from '../../routes'
|
|
13
|
-
import { step, substep, event, error, warn } from '../../utils/log'
|
|
13
|
+
import { step, substep, event, error, wait as wwait, warn, log } from '../../utils/log'
|
|
14
14
|
import { platforms } from './constants'
|
|
15
15
|
|
|
16
16
|
export const _root = join(dirname(new URL(import.meta.url).pathname), '../../../../../')
|
|
@@ -292,7 +292,7 @@ export async function watch(cb: (e: ChokidarEventName | string, file: string) =>
|
|
|
292
292
|
let restartTimeout: NodeJS.Timeout | null = null
|
|
293
293
|
|
|
294
294
|
const watcher = (e: ChokidarEventName) => async (file: string) => {
|
|
295
|
-
|
|
295
|
+
log(getAssetChangeMessage(e, file))
|
|
296
296
|
|
|
297
297
|
if (restartTimeout)
|
|
298
298
|
clearTimeout(restartTimeout)
|
|
@@ -308,7 +308,7 @@ export async function watch(cb: (e: ChokidarEventName | string, file: string) =>
|
|
|
308
308
|
codeWatcher.on('addDir', watcher('addDir'))
|
|
309
309
|
codeWatcher.on('unlinkDir', watcher('unlinkDir'))
|
|
310
310
|
|
|
311
|
-
|
|
311
|
+
wwait('Watching for file changes')
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
export async function wait(ms: number) {
|
package/src/utils/log.ts
CHANGED
|
@@ -43,6 +43,7 @@ export const prefixes = {
|
|
|
43
43
|
info: white(bold(' ')),
|
|
44
44
|
event: green(bold('✓')),
|
|
45
45
|
trace: magenta(bold('»')),
|
|
46
|
+
log: gray(bold('⁕')),
|
|
46
47
|
} as const
|
|
47
48
|
|
|
48
49
|
const LOGGING_METHOD = {
|
|
@@ -76,6 +77,10 @@ function prefixedLog(prefixType: keyof typeof prefixes, ...msg: any[]) {
|
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
export function log(...msg: any[]) {
|
|
81
|
+
prefixedLog('log', ...msg)
|
|
82
|
+
}
|
|
83
|
+
|
|
79
84
|
export function wait(...msg: any[]) {
|
|
80
85
|
prefixedLog('wait', ...msg)
|
|
81
86
|
}
|