@gravito/launchpad 1.2.0 → 1.2.1
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/.turbo/turbo-build.log +18 -0
- package/.turbo/turbo-test$colon$coverage.log +183 -0
- package/.turbo/turbo-test.log +100 -0
- package/.turbo/turbo-typecheck.log +1 -0
- package/CHANGELOG.md +10 -0
- package/debug-launch.ts +4 -1
- package/dist/index.js +0 -4
- package/dist/index.mjs +0 -4
- package/package.json +1 -1
- package/src/Application/MissionControl.ts +9 -0
- package/src/Application/PayloadInjector.ts +9 -0
- package/src/Application/PoolManager.ts +9 -0
- package/src/Application/RefurbishUnit.ts +10 -0
- package/src/Domain/Events.ts +24 -0
- package/src/Domain/Mission.ts +9 -0
- package/src/Domain/Rocket.ts +10 -0
- package/src/Infrastructure/Docker/DockerAdapter.ts +9 -0
- package/src/Infrastructure/Git/ShellGitAdapter.ts +9 -0
- package/src/Infrastructure/GitHub/OctokitGitHubAdapter.ts +9 -0
- package/src/Infrastructure/Persistence/CachedRocketRepository.ts +9 -0
- package/src/Infrastructure/Persistence/InMemoryRocketRepository.ts +9 -0
- package/src/Infrastructure/Router/BunProxyAdapter.ts +9 -0
- package/src/index.ts +24 -12
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mtsup src/index.ts --format cjs,esm --dts[0m
|
|
3
|
+
[34mCLI[39m Building entry: src/index.ts
|
|
4
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
|
+
[34mCLI[39m tsup v8.5.1
|
|
6
|
+
[34mCLI[39m Target: esnext
|
|
7
|
+
[34mCJS[39m Build start
|
|
8
|
+
[34mESM[39m Build start
|
|
9
|
+
[33mCJS[39m [33mYou have emitDecoratorMetadata enabled but @swc/core was not installed, skipping swc plugin[39m
|
|
10
|
+
[33mESM[39m [33mYou have emitDecoratorMetadata enabled but @swc/core was not installed, skipping swc plugin[39m
|
|
11
|
+
[32mCJS[39m [1mdist/index.js [22m[32m27.01 KB[39m
|
|
12
|
+
[32mCJS[39m ⚡️ Build success in 24ms
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m25.50 KB[39m
|
|
14
|
+
[32mESM[39m ⚡️ Build success in 24ms
|
|
15
|
+
DTS Build start
|
|
16
|
+
DTS ⚡️ Build success in 1979ms
|
|
17
|
+
DTS dist/index.d.ts 5.14 KB
|
|
18
|
+
DTS dist/index.d.mts 5.14 KB
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
$ bun test --coverage --coverage-threshold=80
|
|
2
|
+
bun test v1.3.4 (5eb2145b)
|
|
3
|
+
|
|
4
|
+
tests/mission.test.ts:
|
|
5
|
+
(pass) Mission > exposes mission properties [0.31ms]
|
|
6
|
+
|
|
7
|
+
tests/Telemetry.test.ts:
|
|
8
|
+
[MissionControl] 準備發射任務: pr-1
|
|
9
|
+
[MissionControl] 任務 pr-1 映射端口: 3000
|
|
10
|
+
(pass) MissionControl Telemetry > 發射時應該能正確啟動日誌串流與效能監控 [6.79ms]
|
|
11
|
+
|
|
12
|
+
tests/mission-control.test.ts:
|
|
13
|
+
[MissionControl] 準備發射任務: mission-telemetry
|
|
14
|
+
[MissionControl] 任務 mission-telemetry 映射端口: 3000
|
|
15
|
+
[MissionControl] 任務 mission-telemetry TTL 已到期,執行自動回收...
|
|
16
|
+
(pass) MissionControl timers > emits stats and schedules recycle [2.17ms]
|
|
17
|
+
|
|
18
|
+
tests/pool-manager.test.ts:
|
|
19
|
+
[LaunchPad] 正在熱機,準備發射 2 架新火箭...
|
|
20
|
+
(pass) PoolManager > warms up the pool with base containers [1.23ms]
|
|
21
|
+
[LaunchPad] 正在熱機,準備發射 1 架新火箭...
|
|
22
|
+
[LaunchPad] 資源吃緊,正在緊急呼叫後援火箭...
|
|
23
|
+
(pass) PoolManager > assigns missions to idle rockets or creates new ones [1.90ms]
|
|
24
|
+
[LaunchPad] 正在熱機,準備發射 1 架新火箭...
|
|
25
|
+
(pass) PoolManager > recycles rockets through refurbish flow [2.99ms]
|
|
26
|
+
|
|
27
|
+
tests/enterprise-coverage.test.ts:
|
|
28
|
+
(pass) Launchpad enterprise coverage > covers core enterprise primitives [0.56ms]
|
|
29
|
+
|
|
30
|
+
tests/repository.test.ts:
|
|
31
|
+
(pass) InMemoryRocketRepository > stores and retrieves rockets [0.75ms]
|
|
32
|
+
(pass) InMemoryRocketRepository > finds idle rockets [0.19ms]
|
|
33
|
+
|
|
34
|
+
tests/Rocket.test.ts:
|
|
35
|
+
(pass) Rocket > transitions through mission lifecycle and emits events [0.17ms]
|
|
36
|
+
(pass) Rocket > guards invalid transitions [0.19ms]
|
|
37
|
+
(pass) Rocket > assigns domain and serializes/deserializes [0.15ms]
|
|
38
|
+
(pass) Rocket > rejects assigning mission when not idle [0.06ms]
|
|
39
|
+
|
|
40
|
+
tests/Refurbishment.test.ts:
|
|
41
|
+
(pass) RefurbishUnit (Rocket Recovery) > 應該能執行深度清理並將火箭重置為 IDLE [1.11ms]
|
|
42
|
+
[RefurbishUnit] 正在翻新火箭: r1 (容器: c1)
|
|
43
|
+
[RefurbishUnit] 火箭 r1 翻新完成,已進入 IDLE 狀態。
|
|
44
|
+
[RefurbishUnit] 正在翻新火箭: r2 (容器: c2)
|
|
45
|
+
[RefurbishUnit] 清理失敗: Disk Full
|
|
46
|
+
(pass) RefurbishUnit (Rocket Recovery) > 如果清理失敗應該將火箭除役 [0.28ms]
|
|
47
|
+
|
|
48
|
+
tests/payload-injector.test.ts:
|
|
49
|
+
(pass) PayloadInjector > throws when rocket has no mission [1.02ms]
|
|
50
|
+
[PayloadInjector] 正在拉取代碼: https://example.com/repo.git (main)
|
|
51
|
+
[PayloadInjector] 正在注入載荷至容器: container-10
|
|
52
|
+
[PayloadInjector] 正在安裝依賴...
|
|
53
|
+
[PayloadInjector] 點火!
|
|
54
|
+
(pass) PayloadInjector > deploys payload and ignites rocket [0.78ms]
|
|
55
|
+
[PayloadInjector] 正在拉取代碼: https://example.com/repo.git (main)
|
|
56
|
+
[PayloadInjector] 正在注入載荷至容器: container-11
|
|
57
|
+
[PayloadInjector] 正在安裝依賴...
|
|
58
|
+
(pass) PayloadInjector > throws when install fails [4.37ms]
|
|
59
|
+
[PayloadInjector] 正在拉取代碼: https://example.com/repo.git (main)
|
|
60
|
+
[PayloadInjector] 正在注入載荷至容器: container-12
|
|
61
|
+
[PayloadInjector] 正在安裝依賴...
|
|
62
|
+
[PayloadInjector] 點火!
|
|
63
|
+
(pass) PayloadInjector > logs when run command fails but still ignites [8.24ms]
|
|
64
|
+
|
|
65
|
+
tests/docker-adapter.test.ts:
|
|
66
|
+
(pass) DockerAdapter > creates base container when stdout has container id [8.90ms]
|
|
67
|
+
(pass) DockerAdapter > returns container id even when exit code is zero but id is invalid [0.28ms]
|
|
68
|
+
(pass) DockerAdapter > throws when container creation fails [0.70ms]
|
|
69
|
+
(pass) DockerAdapter > getExposedPort parses the first line [1.64ms]
|
|
70
|
+
(pass) DockerAdapter > getExposedPort throws on empty output [6.46ms]
|
|
71
|
+
(pass) DockerAdapter > getExposedPort throws on invalid output [4.70ms]
|
|
72
|
+
(pass) DockerAdapter > copyFiles throws on non-zero exit code [0.54ms]
|
|
73
|
+
(pass) DockerAdapter > removeContainerByLabel removes containers when ids exist [0.72ms]
|
|
74
|
+
(pass) DockerAdapter > executeCommand returns stdout and stderr [3.41ms]
|
|
75
|
+
(pass) DockerAdapter > removeContainer executes docker rm [1.66ms]
|
|
76
|
+
(pass) DockerAdapter > getStats parses cpu and memory output [0.39ms]
|
|
77
|
+
(pass) DockerAdapter > streamLogs forwards stdout and stderr [43.53ms]
|
|
78
|
+
|
|
79
|
+
tests/Integration.test.ts:
|
|
80
|
+
[LaunchPad] 正在熱機,準備發射 1 架新火箭...
|
|
81
|
+
[Test] 容器內 Bun 版本: 1.0.36
|
|
82
|
+
(pass) LaunchPad 集成測試 (真實 Docker) > 應該能成功熱機並在容器內執行指令 [3201.00ms]
|
|
83
|
+
|
|
84
|
+
tests/Deployment.test.ts:
|
|
85
|
+
[LaunchPad] 資源吃緊,正在緊急呼叫後援火箭...
|
|
86
|
+
[PayloadInjector] 正在拉取代碼: http://git (dev)
|
|
87
|
+
[PayloadInjector] 正在注入載荷至容器: cid-1
|
|
88
|
+
[PayloadInjector] 正在安裝依賴...
|
|
89
|
+
[PayloadInjector] 點火!
|
|
90
|
+
(pass) Payload Injection Flow > 應該能從指派任務到成功點火 [1.02ms]
|
|
91
|
+
|
|
92
|
+
tests/PoolManager.test.ts:
|
|
93
|
+
(pass) PoolManager (Application Service) > 應該能正確熱機並指派任務 [1.54ms]
|
|
94
|
+
------------------------------------------------------------|---------|---------|-------------------
|
|
95
|
+
File | % Funcs | % Lines | Uncovered Line #s
|
|
96
|
+
[LaunchPad] 正在熱機,準備發射 2 架新火箭...
|
|
97
|
+
------------------------------------------------------------|---------|---------|-------------------
|
|
98
|
+
All files | 30.25 | 42.00 |
|
|
99
|
+
../core/src/Application.ts | 0.00 | 8.87 | 139-313,325-326,336-337,348,358,368,375,382
|
|
100
|
+
../core/src/ConfigManager.ts | 0.00 | 14.04 | 16-22,29-34,42-75,82
|
|
101
|
+
../core/src/Container.ts | 0.00 | 28.95 | 26,34,41,48-67,74,81-82
|
|
102
|
+
../core/src/ErrorHandler.ts | 0.00 | 3.45 | 23-41,49-75,101-297,304-325,332-357,365-381
|
|
103
|
+
../core/src/Event.ts | 100.00 | 100.00 |
|
|
104
|
+
../core/src/EventManager.ts | 0.00 | 7.01 | 78,85,108-126,136-243,250-256,263-271
|
|
105
|
+
../core/src/GlobalErrorHandlers.ts | 0.00 | 1.19 | 58-72,78-88,92-101,106-186,191-210,214-228,239-252
|
|
106
|
+
../core/src/GravitoServer.ts | 0.00 | 8.77 | 25-76
|
|
107
|
+
../core/src/HookManager.ts | 0.00 | 8.33 | 37-73,93-121
|
|
108
|
+
../core/src/Logger.ts | 0.00 | 55.56 | 17,21,25
|
|
109
|
+
../core/src/PlanetCore.ts | 0.00 | 10.53 | 117-131,162-208,218-227,237-269,273-390,394-443,453-468,485-501
|
|
110
|
+
../core/src/Route.ts | 0.00 | 44.44 | 18-22,28-29,44,55,66,77,88,92,96
|
|
111
|
+
../core/src/Router.ts | 0.00 | 7.68 | 68-121,131-154,182-184,190-193,201-205,212,224-232,243-251,262-270,281-289,300-308,312-354,365-380,414-459,466-471,478-505,512,522-524,531,538-553,557-600,607,614,622,636-644,658-666,680-688,702-710,724-732,743-758,765-803,810-892,899-913
|
|
112
|
+
../core/src/ServiceProvider.ts | 0.00 | 15.07 | 58,91,114-150,179-188,198-209
|
|
113
|
+
../core/src/adapters/GravitoEngineAdapter.ts | 0.00 | 30.43 | 27-31,35-44,48-50,54,58,62-65,69,73,78-81,85-86
|
|
114
|
+
../core/src/adapters/PhotonAdapter.ts | 0.00 | 13.93 | 46,53-55,62-108,112,116,120,124,130-163,167-168,191-195,203-207,214-257,261-262,266-269,273-276,280-283,287-298,302-309,313-318,322,326,330,334,341-355,359,363,367-446,462-467,471-473,487-492,501-512,521-528,564-584,592,596-612,616-626,630-635,639,643-651,656,660-675,683-695,708-710
|
|
115
|
+
../core/src/adapters/bun/BunContext.ts | 0.00 | 12.58 | 38-44,52-75,80-86,90-96,100-106,110-116,120-125,129-134,138,142,146,150-182,189-205,209,214,218-223
|
|
116
|
+
../core/src/adapters/bun/BunNativeAdapter.ts | 0.00 | 10.23 | 21-23,32-36,40-46,50,54,58-87,91,95,99-207
|
|
117
|
+
../core/src/adapters/bun/BunRequest.ts | 0.00 | 10.62 | 13-17,22-34,39,43,47-55,59-62,68-108,114,118-131,135-146
|
|
118
|
+
../core/src/adapters/bun/RadixNode.ts | 0.00 | 17.65 | 39-40,44-52,56-72
|
|
119
|
+
../core/src/adapters/bun/RadixRouter.ts | 0.00 | 8.13 | 17,24-62,69-84,88-148,152-162,169-175,182-193
|
|
120
|
+
../core/src/adapters/bun/types.ts | 100.00 | 100.00 |
|
|
121
|
+
../core/src/adapters/types.ts | 0.00 | 0.00 | 280-287
|
|
122
|
+
../core/src/engine/AOTRouter.ts | 0.00 | 10.78 | 67-85,93-133,144-145,157-159,172-208,215,228-272,279,294-306,320-327,334-345
|
|
123
|
+
../core/src/engine/FastContext.ts | 0.00 | 19.09 | 30,37-45,52-61,65-84,88-89,93-94,98-101,105-109,113-129,133-134,138-169,192-198,208-212,219-223,231-236,240-245,249-254,258-263,267-271,275-280,284,288,292,296-319,329-334,338,349,353,361-363
|
|
124
|
+
../core/src/engine/Gravito.ts | 0.00 | 14.67 | 38-52,82-103,118,125,132,139,146,153,160,167-171,184-197,208-214,225-226,233-255,293-322,330-367,374-391,398-410,417-421,428-456,463-519
|
|
125
|
+
../core/src/engine/MinimalContext.ts | 0.00 | 21.57 | 23-37,41,45,52-64,68,72-84,88,92-112,130,139-142,146-149,153-156,160-163,167-170,174-177,183-187,195-198,202,206,210,214-225,229,235-237
|
|
126
|
+
../core/src/engine/analyzer.ts | 0.00 | 2.08 | 25-49,56-77
|
|
127
|
+
../core/src/engine/constants.ts | 100.00 | 100.00 |
|
|
128
|
+
../core/src/engine/index.ts | 100.00 | 100.00 |
|
|
129
|
+
../core/src/engine/path.ts | 0.00 | 2.63 | 22-43,51-65
|
|
130
|
+
../core/src/engine/pool.ts | 0.00 | 16.67 | 44-46,58-64,76-79,89-103,114-119
|
|
131
|
+
../core/src/exceptions/AuthenticationException.ts | 0.00 | 42.86 | 8-11
|
|
132
|
+
../core/src/exceptions/AuthorizationException.ts | 0.00 | 42.86 | 8-11
|
|
133
|
+
../core/src/exceptions/GravitoException.ts | 0.00 | 19.05 | 24-34,39-44
|
|
134
|
+
../core/src/exceptions/HttpException.ts | 0.00 | 60.00 | 9-10
|
|
135
|
+
../core/src/exceptions/ModelNotFoundException.ts | 0.00 | 25.00 | 11-19
|
|
136
|
+
../core/src/exceptions/ValidationException.ts | 0.00 | 35.71 | 22-26,30-31,35-36
|
|
137
|
+
../core/src/exceptions/index.ts | 100.00 | 100.00 |
|
|
138
|
+
../core/src/helpers.ts | 0.00 | 23.14 | 19,54-59,81-82,107-108,133-139,143-147,176-196,218,222-228,248-253,272-277,306-308,323,335,356-359,381-384,403,417,438-441,461-463,483-489
|
|
139
|
+
../core/src/helpers/Arr.ts | 0.00 | 14.58 | 9-13,17,21,25-28,32-41,45-54,58-64,68-75,79-92,96-109,113-120
|
|
140
|
+
../core/src/helpers/Str.ts | 0.00 | 18.56 | 5-10,14-17,27,31,35-41,45-51,55-61,65-66,70-71,75-77,81-89,93-95,99-105,109-117,121-124,128-134
|
|
141
|
+
../core/src/helpers/data.ts | 0.00 | 2.17 | 13-30,34-47,51-64,68-88,96-113,121-134,142-177
|
|
142
|
+
../core/src/helpers/errors.ts | 0.00 | 7.69 | 26-43,51-53,61-63
|
|
143
|
+
../core/src/helpers/response.ts | 0.00 | 12.50 | 29,37-44,52-56,64-70
|
|
144
|
+
../core/src/http/CookieJar.ts | 0.00 | 12.33 | 33-46,53-74,81,88,95-117,124-126
|
|
145
|
+
../core/src/http/middleware/BodySizeLimit.ts | 0.00 | 2.70 | 20-55
|
|
146
|
+
../core/src/http/middleware/Cors.ts | 0.00 | 1.64 | 23-35,43-89
|
|
147
|
+
../core/src/http/middleware/Csrf.ts | 0.00 | 5.05 | 19-24,28-34,38,42-67,75-91,99-135
|
|
148
|
+
../core/src/http/middleware/HeaderTokenGate.ts | 0.00 | 4.55 | 25-35,45-54
|
|
149
|
+
../core/src/http/middleware/SecurityHeaders.ts | 0.00 | 1.67 | 28,32-35,39-46,54-99
|
|
150
|
+
../core/src/http/middleware/ThrottleRequests.ts | 0.00 | 8.51 | 31-73
|
|
151
|
+
../core/src/index.ts | 0.00 | 96.97 |
|
|
152
|
+
../core/src/runtime.ts | 21.05 | 11.87 | 118-131,138-145,149-166,175,188-190,193-216,221-225,230-325,330-420,425-448,467-470,481-518,526-533
|
|
153
|
+
../core/src/security/Encrypter.ts | 0.00 | 13.70 | 21-35,42-59,66-82,86-88,92-97,102-103,110-111
|
|
154
|
+
../core/src/security/Hasher.ts | 0.00 | 9.09 | 25-43
|
|
155
|
+
../core/src/testing/HttpTester.ts | 0.00 | 4.27 | 11-121
|
|
156
|
+
../core/src/testing/TestResponse.ts | 0.00 | 10.92 | 16-17,24,31,38,45,52,59-124,131-132,139-169
|
|
157
|
+
../core/src/testing/index.ts | 100.00 | 100.00 |
|
|
158
|
+
../core/src/types/events.ts | 0.00 | 14.29 | 91-93,101-104,111-125,132-139
|
|
159
|
+
../enterprise/src/Application/Command.ts | 100.00 | 100.00 |
|
|
160
|
+
../enterprise/src/Application/Query.ts | 100.00 | 100.00 |
|
|
161
|
+
../enterprise/src/Application/UseCase.ts | 100.00 | 100.00 |
|
|
162
|
+
../enterprise/src/Domain/AggregateRoot.ts | 50.00 | 55.56 | 1-8
|
|
163
|
+
../enterprise/src/Domain/DomainEvent.ts | 50.00 | 55.56 | 16-19
|
|
164
|
+
../enterprise/src/Domain/Entity.ts | 100.00 | 100.00 |
|
|
165
|
+
../enterprise/src/Domain/Repository.ts | 100.00 | 100.00 |
|
|
166
|
+
../enterprise/src/Domain/ValueObject.ts | 100.00 | 100.00 |
|
|
167
|
+
../enterprise/src/index.ts | 100.00 | 100.00 |
|
|
168
|
+
src/Application/MissionControl.ts | 100.00 | 100.00 |
|
|
169
|
+
src/Application/PayloadInjector.ts | 100.00 | 100.00 |
|
|
170
|
+
src/Application/PoolManager.ts | 100.00 | 100.00 |
|
|
171
|
+
src/Application/RefurbishUnit.ts | 100.00 | 100.00 |
|
|
172
|
+
src/Domain/Events.ts | 100.00 | 100.00 |
|
|
173
|
+
src/Domain/Mission.ts | 83.33 | 100.00 |
|
|
174
|
+
src/Domain/Rocket.ts | 100.00 | 100.00 |
|
|
175
|
+
src/Domain/RocketStatus.ts | 100.00 | 100.00 |
|
|
176
|
+
src/Infrastructure/Docker/DockerAdapter.ts | 94.44 | 100.00 |
|
|
177
|
+
src/Infrastructure/Persistence/InMemoryRocketRepository.ts | 90.91 | 100.00 |
|
|
178
|
+
------------------------------------------------------------|---------|---------|-------------------
|
|
179
|
+
|
|
180
|
+
34 pass
|
|
181
|
+
0 fail
|
|
182
|
+
99 expect() calls
|
|
183
|
+
Ran 34 tests across 13 files. [4.34s]
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mbun test[0m
|
|
3
|
+
[0m[1mbun test [0m[2mv1.3.4 (5eb2145b)[0m
|
|
4
|
+
[0m
|
|
5
|
+
tests/mission.test.ts:
|
|
6
|
+
[0m[32m✓[0m [0mMission[2m >[0m[1m exposes mission properties[0m [0m[2m[0.45ms[0m[2m][0m
|
|
7
|
+
[0m
|
|
8
|
+
tests/Telemetry.test.ts:
|
|
9
|
+
[MissionControl] 準備發射任務: pr-1
|
|
10
|
+
[MissionControl] 任務 pr-1 映射端口: 3000
|
|
11
|
+
[0m[32m✓[0m [0mMissionControl Telemetry[2m >[0m[1m 發射時應該能正確啟動日誌串流與效能監控[0m [0m[2m[1.84ms[0m[2m][0m
|
|
12
|
+
[0m
|
|
13
|
+
tests/mission-control.test.ts:
|
|
14
|
+
[MissionControl] 準備發射任務: mission-telemetry
|
|
15
|
+
[MissionControl] 任務 mission-telemetry 映射端口: 3000
|
|
16
|
+
[MissionControl] 任務 mission-telemetry TTL 已到期,執行自動回收...
|
|
17
|
+
[0m[32m✓[0m [0mMissionControl timers[2m >[0m[1m emits stats and schedules recycle[0m [0m[2m[0.92ms[0m[2m][0m
|
|
18
|
+
[0m
|
|
19
|
+
tests/pool-manager.test.ts:
|
|
20
|
+
[LaunchPad] 正在熱機,準備發射 2 架新火箭...
|
|
21
|
+
[0m[32m✓[0m [0mPoolManager[2m >[0m[1m warms up the pool with base containers[0m [0m[2m[0.62ms[0m[2m][0m
|
|
22
|
+
[LaunchPad] 正在熱機,準備發射 1 架新火箭...
|
|
23
|
+
[LaunchPad] 資源吃緊,正在緊急呼叫後援火箭...
|
|
24
|
+
[0m[32m✓[0m [0mPoolManager[2m >[0m[1m assigns missions to idle rockets or creates new ones[0m [0m[2m[1.08ms[0m[2m][0m
|
|
25
|
+
[LaunchPad] 正在熱機,準備發射 1 架新火箭...
|
|
26
|
+
[0m[32m✓[0m [0mPoolManager[2m >[0m[1m recycles rockets through refurbish flow[0m [0m[2m[0.34ms[0m[2m][0m
|
|
27
|
+
[0m
|
|
28
|
+
tests/enterprise-coverage.test.ts:
|
|
29
|
+
[0m[32m✓[0m [0mLaunchpad enterprise coverage[2m >[0m[1m covers core enterprise primitives[0m [0m[2m[0.20ms[0m[2m][0m
|
|
30
|
+
[0m
|
|
31
|
+
tests/repository.test.ts:
|
|
32
|
+
[0m[32m✓[0m [0mInMemoryRocketRepository[2m >[0m[1m stores and retrieves rockets[0m [0m[2m[0.11ms[0m[2m][0m
|
|
33
|
+
[0m[32m✓[0m [0mInMemoryRocketRepository[2m >[0m[1m finds idle rockets[0m [0m[2m[0.10ms[0m[2m][0m
|
|
34
|
+
[0m
|
|
35
|
+
tests/Rocket.test.ts:
|
|
36
|
+
[0m[32m✓[0m [0mRocket[2m >[0m[1m transitions through mission lifecycle and emits events[0m [0m[2m[0.25ms[0m[2m][0m
|
|
37
|
+
[0m[32m✓[0m [0mRocket[2m >[0m[1m guards invalid transitions[0m [0m[2m[0.12ms[0m[2m][0m
|
|
38
|
+
[0m[32m✓[0m [0mRocket[2m >[0m[1m assigns domain and serializes/deserializes[0m [0m[2m[0.04ms[0m[2m][0m
|
|
39
|
+
[0m[32m✓[0m [0mRocket[2m >[0m[1m rejects assigning mission when not idle[0m [0m[2m[0.12ms[0m[2m][0m
|
|
40
|
+
[0m
|
|
41
|
+
tests/Refurbishment.test.ts:
|
|
42
|
+
[RefurbishUnit] 正在翻新火箭: r1 (容器: c1)
|
|
43
|
+
[RefurbishUnit] 火箭 r1 翻新完成,已進入 IDLE 狀態。
|
|
44
|
+
[0m[32m✓[0m [0mRefurbishUnit (Rocket Recovery)[2m >[0m[1m 應該能執行深度清理並將火箭重置為 IDLE[0m [0m[2m[0.66ms[0m[2m][0m
|
|
45
|
+
[RefurbishUnit] 正在翻新火箭: r2 (容器: c2)
|
|
46
|
+
[0m[31m[RefurbishUnit] 清理失敗: Disk Full[0m
|
|
47
|
+
[0m[32m✓[0m [0mRefurbishUnit (Rocket Recovery)[2m >[0m[1m 如果清理失敗應該將火箭除役[0m [0m[2m[0.18ms[0m[2m][0m
|
|
48
|
+
[0m
|
|
49
|
+
tests/payload-injector.test.ts:
|
|
50
|
+
[0m[32m✓[0m [0mPayloadInjector[2m >[0m[1m throws when rocket has no mission[0m [0m[2m[0.51ms[0m[2m][0m
|
|
51
|
+
[PayloadInjector] 正在拉取代碼: https://example.com/repo.git (main)
|
|
52
|
+
[PayloadInjector] 正在注入載荷至容器: container-10
|
|
53
|
+
[PayloadInjector] 正在安裝依賴...
|
|
54
|
+
[PayloadInjector] 點火!
|
|
55
|
+
[0m[32m✓[0m [0mPayloadInjector[2m >[0m[1m deploys payload and ignites rocket[0m [0m[2m[0.28ms[0m[2m][0m
|
|
56
|
+
[PayloadInjector] 正在拉取代碼: https://example.com/repo.git (main)
|
|
57
|
+
[PayloadInjector] 正在注入載荷至容器: container-11
|
|
58
|
+
[PayloadInjector] 正在安裝依賴...
|
|
59
|
+
[0m[32m✓[0m [0mPayloadInjector[2m >[0m[1m throws when install fails[0m [0m[2m[0.14ms[0m[2m][0m
|
|
60
|
+
[PayloadInjector] 正在拉取代碼: https://example.com/repo.git (main)
|
|
61
|
+
[PayloadInjector] 正在注入載荷至容器: container-12
|
|
62
|
+
[PayloadInjector] 正在安裝依賴...
|
|
63
|
+
[PayloadInjector] 點火!
|
|
64
|
+
[0m[32m✓[0m [0mPayloadInjector[2m >[0m[1m logs when run command fails but still ignites[0m [0m[2m[1.62ms[0m[2m][0m
|
|
65
|
+
[0m
|
|
66
|
+
tests/docker-adapter.test.ts:
|
|
67
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m creates base container when stdout has container id[0m [0m[2m[9.55ms[0m[2m][0m
|
|
68
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m returns container id even when exit code is zero but id is invalid[0m [0m[2m[0.19ms[0m[2m][0m
|
|
69
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m throws when container creation fails[0m [0m[2m[0.09ms[0m[2m][0m
|
|
70
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m getExposedPort parses the first line[0m [0m[2m[1.81ms[0m[2m][0m
|
|
71
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m getExposedPort throws on empty output[0m [0m[2m[3.29ms[0m[2m][0m
|
|
72
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m getExposedPort throws on invalid output[0m [0m[2m[1.47ms[0m[2m][0m
|
|
73
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m copyFiles throws on non-zero exit code[0m [0m[2m[0.33ms[0m[2m][0m
|
|
74
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m removeContainerByLabel removes containers when ids exist[0m [0m[2m[0.22ms[0m[2m][0m
|
|
75
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m executeCommand returns stdout and stderr[0m [0m[2m[0.12ms[0m[2m][0m
|
|
76
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m removeContainer executes docker rm[0m [0m[2m[0.09ms[0m[2m][0m
|
|
77
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m getStats parses cpu and memory output[0m [0m[2m[0.13ms[0m[2m][0m
|
|
78
|
+
[0m[32m✓[0m [0mDockerAdapter[2m >[0m[1m streamLogs forwards stdout and stderr[0m [0m[2m[4.70ms[0m[2m][0m
|
|
79
|
+
[0m
|
|
80
|
+
tests/Integration.test.ts:
|
|
81
|
+
[LaunchPad] 正在熱機,準備發射 1 架新火箭...
|
|
82
|
+
[Test] 容器內 Bun 版本: 1.0.36
|
|
83
|
+
[0m[32m✓[0m [0mLaunchPad 集成測試 (真實 Docker)[2m >[0m[1m 應該能成功熱機並在容器內執行指令[0m [0m[2m[[1m1171.83ms[0m[2m][0m
|
|
84
|
+
[0m
|
|
85
|
+
tests/Deployment.test.ts:
|
|
86
|
+
[LaunchPad] 資源吃緊,正在緊急呼叫後援火箭...
|
|
87
|
+
[PayloadInjector] 正在拉取代碼: http://git (dev)
|
|
88
|
+
[PayloadInjector] 正在注入載荷至容器: cid-1
|
|
89
|
+
[PayloadInjector] 正在安裝依賴...
|
|
90
|
+
[PayloadInjector] 點火!
|
|
91
|
+
[0m[32m✓[0m [0mPayload Injection Flow[2m >[0m[1m 應該能從指派任務到成功點火[0m [0m[2m[0.29ms[0m[2m][0m
|
|
92
|
+
[0m
|
|
93
|
+
tests/PoolManager.test.ts:
|
|
94
|
+
[LaunchPad] 正在熱機,準備發射 2 架新火箭...
|
|
95
|
+
[0m[32m✓[0m [0mPoolManager (Application Service)[2m >[0m[1m 應該能正確熱機並指派任務[0m [0m[2m[0.24ms[0m[2m][0m
|
|
96
|
+
|
|
97
|
+
[0m[32m 34 pass[0m
|
|
98
|
+
[0m[2m 0 fail[0m
|
|
99
|
+
99 expect() calls
|
|
100
|
+
Ran 34 tests across 13 files. [0m[2m[[1m1499.00ms[0m[2m][0m
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ bun tsc -p tsconfig.json --noEmit --skipLibCheck
|
package/CHANGELOG.md
CHANGED
package/debug-launch.ts
CHANGED
|
@@ -21,7 +21,10 @@ async function run() {
|
|
|
21
21
|
console.log('🧹 Cleaning up old containers...')
|
|
22
22
|
await runtime.spawn(['docker', 'rm', '-f', ...containers.trim().split('\n')]).exited
|
|
23
23
|
}
|
|
24
|
-
} catch
|
|
24
|
+
} catch {
|
|
25
|
+
// Intentionally ignored: Container cleanup is best-effort.
|
|
26
|
+
// Failure could mean containers don't exist or Docker is unavailable, which is acceptable.
|
|
27
|
+
}
|
|
25
28
|
|
|
26
29
|
// 2. Start Server
|
|
27
30
|
const config = await bootstrapLaunchpad()
|
package/dist/index.js
CHANGED
|
@@ -648,10 +648,6 @@ var BunProxyAdapter = class {
|
|
|
648
648
|
var LaunchpadServiceProvider = class extends import_core4.ServiceProvider {
|
|
649
649
|
register(container) {
|
|
650
650
|
if (!container.has("cache")) {
|
|
651
|
-
const cacheFromServices = this.core?.services?.get("cache");
|
|
652
|
-
if (cacheFromServices) {
|
|
653
|
-
container.instance("cache", cacheFromServices);
|
|
654
|
-
}
|
|
655
651
|
}
|
|
656
652
|
container.singleton("launchpad.docker", () => new DockerAdapter());
|
|
657
653
|
container.singleton("launchpad.git", () => new ShellGitAdapter());
|
package/dist/index.mjs
CHANGED
|
@@ -616,10 +616,6 @@ var BunProxyAdapter = class {
|
|
|
616
616
|
var LaunchpadServiceProvider = class extends ServiceProvider {
|
|
617
617
|
register(container) {
|
|
618
618
|
if (!container.has("cache")) {
|
|
619
|
-
const cacheFromServices = this.core?.services?.get("cache");
|
|
620
|
-
if (cacheFromServices) {
|
|
621
|
-
container.instance("cache", cacheFromServices);
|
|
622
|
-
}
|
|
623
619
|
}
|
|
624
620
|
container.singleton("launchpad.docker", () => new DockerAdapter());
|
|
625
621
|
container.singleton("launchpad.git", () => new ShellGitAdapter());
|
package/package.json
CHANGED
|
@@ -3,6 +3,15 @@ import type { Mission } from '../Domain/Mission'
|
|
|
3
3
|
import type { PayloadInjector } from './PayloadInjector'
|
|
4
4
|
import type { PoolManager } from './PoolManager'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* MissionControl orchestrates the high-level process of launching missions.
|
|
8
|
+
*
|
|
9
|
+
* it coordinates between the `PoolManager`, `PayloadInjector`, and `DockerAdapter`
|
|
10
|
+
* to deploy code into containers, assign domains, and monitor execution.
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
* @since 3.0.0
|
|
14
|
+
*/
|
|
6
15
|
export class MissionControl {
|
|
7
16
|
constructor(
|
|
8
17
|
private poolManager: PoolManager,
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { IDockerAdapter, IGitAdapter } from '../Domain/Interfaces'
|
|
2
2
|
import type { Rocket } from '../Domain/Rocket'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* PayloadInjector is responsible for deploying application code into Rocket containers.
|
|
6
|
+
*
|
|
7
|
+
* It clones the repository, copies files into the container, installs
|
|
8
|
+
* dependencies (using Bun), and starts the application.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
* @since 3.0.0
|
|
12
|
+
*/
|
|
4
13
|
export class PayloadInjector {
|
|
5
14
|
constructor(
|
|
6
15
|
private docker: IDockerAdapter,
|
|
@@ -3,6 +3,15 @@ import type { Mission } from '../Domain/Mission'
|
|
|
3
3
|
import { Rocket } from '../Domain/Rocket'
|
|
4
4
|
import type { RefurbishUnit } from './RefurbishUnit'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* PoolManager handles the lifecycle and pooling of Rocket containers.
|
|
8
|
+
*
|
|
9
|
+
* It manages a pool of pre-warmed containers to ensure fast deployment of
|
|
10
|
+
* new missions. It also handles rocket assignment and recycling (refurbishment).
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
* @since 3.0.0
|
|
14
|
+
*/
|
|
6
15
|
export class PoolManager {
|
|
7
16
|
constructor(
|
|
8
17
|
private dockerAdapter: IDockerAdapter,
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import type { IDockerAdapter } from '../Domain/Interfaces'
|
|
2
2
|
import type { Rocket } from '../Domain/Rocket'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* RefurbishUnit handles the cleaning and restoration of Rocket containers.
|
|
6
|
+
*
|
|
7
|
+
* After a mission is complete, this unit resets the container environment
|
|
8
|
+
* (clearing files, stopping processes) so the container can be returned
|
|
9
|
+
* to the idle pool for future reuse.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @since 3.0.0
|
|
13
|
+
*/
|
|
4
14
|
export class RefurbishUnit {
|
|
5
15
|
constructor(private docker: IDockerAdapter) {}
|
|
6
16
|
|
package/src/Domain/Events.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { DomainEvent } from '@gravito/enterprise'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Event emitted when a mission is assigned to a rocket.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
* @since 3.0.0
|
|
8
|
+
*/
|
|
3
9
|
export class MissionAssigned extends DomainEvent {
|
|
4
10
|
constructor(
|
|
5
11
|
public readonly rocketId: string,
|
|
@@ -9,18 +15,36 @@ export class MissionAssigned extends DomainEvent {
|
|
|
9
15
|
}
|
|
10
16
|
}
|
|
11
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Event emitted when a rocket starts its mission (application started).
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
* @since 3.0.0
|
|
23
|
+
*/
|
|
12
24
|
export class RocketIgnited extends DomainEvent {
|
|
13
25
|
constructor(public readonly rocketId: string) {
|
|
14
26
|
super()
|
|
15
27
|
}
|
|
16
28
|
}
|
|
17
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Event emitted when a rocket mission is completed or terminated.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
* @since 3.0.0
|
|
35
|
+
*/
|
|
18
36
|
export class RocketSplashedDown extends DomainEvent {
|
|
19
37
|
constructor(public readonly rocketId: string) {
|
|
20
38
|
super()
|
|
21
39
|
}
|
|
22
40
|
}
|
|
23
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Event emitted when a rocket has finished the refurbishment process.
|
|
44
|
+
*
|
|
45
|
+
* @public
|
|
46
|
+
* @since 3.0.0
|
|
47
|
+
*/
|
|
24
48
|
export class RefurbishmentCompleted extends DomainEvent {
|
|
25
49
|
constructor(public readonly rocketId: string) {
|
|
26
50
|
super()
|
package/src/Domain/Mission.ts
CHANGED
|
@@ -7,6 +7,15 @@ interface MissionProps {
|
|
|
7
7
|
commitSha: string // Commit Hash
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Mission represents a deployment task for a specific code version.
|
|
12
|
+
*
|
|
13
|
+
* It is a Value Object containing information about the source repository,
|
|
14
|
+
* branch, and commit to be deployed.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
* @since 3.0.0
|
|
18
|
+
*/
|
|
10
19
|
export class Mission extends ValueObject<MissionProps> {
|
|
11
20
|
get id() {
|
|
12
21
|
return this.props.id
|
package/src/Domain/Rocket.ts
CHANGED
|
@@ -8,6 +8,16 @@ import {
|
|
|
8
8
|
import type { Mission } from './Mission'
|
|
9
9
|
import { RocketStatus } from './RocketStatus'
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Rocket represents a managed application container within Launchpad.
|
|
13
|
+
*
|
|
14
|
+
* It acts as an Aggregate Root in the domain, maintaining its lifecycle state
|
|
15
|
+
* (IDLE, PREPARING, ORBITING, etc.) and emitting domain events when
|
|
16
|
+
* state transitions occur.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
* @since 3.0.0
|
|
20
|
+
*/
|
|
11
21
|
export class Rocket extends AggregateRoot<string> {
|
|
12
22
|
private _status: RocketStatus = RocketStatus.IDLE
|
|
13
23
|
private _currentMission: Mission | null = null
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { getRuntimeAdapter } from '@gravito/core'
|
|
2
2
|
import type { IDockerAdapter } from '../../Domain/Interfaces'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* DockerAdapter implements the `IDockerAdapter` interface using the Docker CLI.
|
|
6
|
+
*
|
|
7
|
+
* It manages the lifecycle of Docker containers used as "Rockets" in Launchpad,
|
|
8
|
+
* including creation, command execution, file copying, and metrics collection.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
* @since 3.0.0
|
|
12
|
+
*/
|
|
4
13
|
export class DockerAdapter implements IDockerAdapter {
|
|
5
14
|
private baseImage = 'oven/bun:1.0-slim'
|
|
6
15
|
private runtime = getRuntimeAdapter()
|
|
@@ -2,6 +2,15 @@ import { mkdir } from 'node:fs/promises'
|
|
|
2
2
|
import { getRuntimeAdapter } from '@gravito/core'
|
|
3
3
|
import type { IGitAdapter } from '../../Domain/Interfaces'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* ShellGitAdapter implements the `IGitAdapter` interface using the Git CLI.
|
|
7
|
+
*
|
|
8
|
+
* It provides methods for cloning repositories to a temporary directory
|
|
9
|
+
* for deployment into Rocket containers.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @since 3.0.0
|
|
13
|
+
*/
|
|
5
14
|
export class ShellGitAdapter implements IGitAdapter {
|
|
6
15
|
private baseDir = '/tmp/gravito-launchpad-git'
|
|
7
16
|
|
|
@@ -2,6 +2,15 @@ import { createHmac, timingSafeEqual } from 'node:crypto'
|
|
|
2
2
|
import { Octokit } from '@octokit/rest'
|
|
3
3
|
import type { IGitHubAdapter } from '../../Domain/Interfaces'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* OctokitGitHubAdapter implements the `IGitHubAdapter` interface using the Octokit library.
|
|
7
|
+
*
|
|
8
|
+
* It provides methods for verifying GitHub webhook signatures and interacting with
|
|
9
|
+
* the GitHub API, such as posting comments on Pull Requests.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @since 3.0.0
|
|
13
|
+
*/
|
|
5
14
|
export class OctokitGitHubAdapter implements IGitHubAdapter {
|
|
6
15
|
private octokit: Octokit
|
|
7
16
|
|
|
@@ -2,6 +2,15 @@ import type { CacheService } from '@gravito/core'
|
|
|
2
2
|
import type { IRocketRepository } from '../../Domain/Interfaces'
|
|
3
3
|
import { Rocket } from '../../Domain/Rocket'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* CachedRocketRepository implements the `IRocketRepository` interface using Gravito's `CacheService`.
|
|
7
|
+
*
|
|
8
|
+
* It provides a persistent (depending on cache driver) storage for Rocket
|
|
9
|
+
* metadata, allowing Launchpad to track container states across requests.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @since 3.0.0
|
|
13
|
+
*/
|
|
5
14
|
export class CachedRocketRepository implements IRocketRepository {
|
|
6
15
|
private CACHE_KEY = 'launchpad:rockets'
|
|
7
16
|
|
|
@@ -2,6 +2,15 @@ import type { IRocketRepository } from '../../Domain/Interfaces'
|
|
|
2
2
|
import type { Rocket } from '../../Domain/Rocket'
|
|
3
3
|
import { RocketStatus } from '../../Domain/RocketStatus'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* InMemoryRocketRepository implements the `IRocketRepository` interface using an in-memory Map.
|
|
7
|
+
*
|
|
8
|
+
* This repository is suitable for testing or development environments where
|
|
9
|
+
* persistence across restarts is not required.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @since 3.0.0
|
|
13
|
+
*/
|
|
5
14
|
export class InMemoryRocketRepository implements IRocketRepository {
|
|
6
15
|
private rockets = new Map<string, Rocket>()
|
|
7
16
|
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { getRuntimeAdapter } from '@gravito/core'
|
|
2
2
|
import type { IRouterAdapter } from '../../Domain/Interfaces'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* BunProxyAdapter implements the `IRouterAdapter` interface using Bun's native HTTP server.
|
|
6
|
+
*
|
|
7
|
+
* It provides a dynamic reverse proxy that routes requests to specific Rocket
|
|
8
|
+
* containers based on the `Host` header.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
* @since 3.0.0
|
|
12
|
+
*/
|
|
4
13
|
export class BunProxyAdapter implements IRouterAdapter {
|
|
5
14
|
private routes = new Map<string, string>() // domain -> targetUrl
|
|
6
15
|
|
package/src/index.ts
CHANGED
|
@@ -26,10 +26,8 @@ export * from './Domain/RocketStatus'
|
|
|
26
26
|
class LaunchpadServiceProvider extends ServiceProvider {
|
|
27
27
|
register(container: Container): void {
|
|
28
28
|
if (!container.has('cache')) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
container.instance('cache', cacheFromServices)
|
|
32
|
-
}
|
|
29
|
+
// 在新的架構中,如果 core 有預設綁定,可以直接通過 container.make 獲取
|
|
30
|
+
// 這裡如果只是想從父容器繼承,通常不需要額外操作,除非是在不同的 instance 中。
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
container.singleton('launchpad.docker', () => new DockerAdapter())
|
|
@@ -101,11 +99,24 @@ class LaunchpadServiceProvider extends ServiceProvider {
|
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
/**
|
|
104
|
-
*
|
|
102
|
+
* LaunchpadOrbit provides automated deployment and preview capabilities for Gravito.
|
|
103
|
+
* It integrates with Docker and GitHub to provide "Preview Deployments" for Pull Requests.
|
|
104
|
+
*
|
|
105
|
+
* @public
|
|
105
106
|
*/
|
|
106
107
|
export class LaunchpadOrbit implements GravitoOrbit {
|
|
108
|
+
/**
|
|
109
|
+
* Create a new LaunchpadOrbit instance.
|
|
110
|
+
* @param ripple - Ripple instance for real-time telemetry communication.
|
|
111
|
+
*/
|
|
107
112
|
constructor(private ripple: OrbitRipple) {}
|
|
108
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Install the Launchpad orbit into PlanetCore.
|
|
116
|
+
* Registers the service provider and sets up webhook routes for deployment.
|
|
117
|
+
*
|
|
118
|
+
* @param core - The PlanetCore instance.
|
|
119
|
+
*/
|
|
109
120
|
async install(core: PlanetCore): Promise<void> {
|
|
110
121
|
core.register(new LaunchpadServiceProvider())
|
|
111
122
|
|
|
@@ -139,7 +150,7 @@ export class LaunchpadOrbit implements GravitoOrbit {
|
|
|
139
150
|
|
|
140
151
|
const ctrl = core.container.make<MissionControl>('launchpad.ctrl')
|
|
141
152
|
const rocketId = await ctrl.launch(mission, (type, data) => {
|
|
142
|
-
//
|
|
153
|
+
// Correctly broadcast telemetry data via Ripple
|
|
143
154
|
this.ripple.getServer().broadcast('telemetry', 'telemetry.data', { type, data })
|
|
144
155
|
})
|
|
145
156
|
|
|
@@ -188,7 +199,12 @@ export class LaunchpadOrbit implements GravitoOrbit {
|
|
|
188
199
|
}
|
|
189
200
|
|
|
190
201
|
/**
|
|
191
|
-
*
|
|
202
|
+
* Bootstrap the Launchpad application.
|
|
203
|
+
* Initializes PlanetCore with necessary orbits (Cache, Ripple, Launchpad)
|
|
204
|
+
* and returns the configuration for the server entry point.
|
|
205
|
+
*
|
|
206
|
+
* @returns Server configuration object including port and fetch handler.
|
|
207
|
+
* @public
|
|
192
208
|
*/
|
|
193
209
|
export async function bootstrapLaunchpad() {
|
|
194
210
|
const ripple = new OrbitRipple({ path: '/ws' })
|
|
@@ -199,11 +215,7 @@ export async function bootstrapLaunchpad() {
|
|
|
199
215
|
PORT: 4000,
|
|
200
216
|
CACHE_DRIVER: 'file',
|
|
201
217
|
},
|
|
202
|
-
orbits: [
|
|
203
|
-
new OrbitCache(),
|
|
204
|
-
ripple,
|
|
205
|
-
new LaunchpadOrbit(ripple), // 傳入實例
|
|
206
|
-
],
|
|
218
|
+
orbits: [new OrbitCache(), ripple, new LaunchpadOrbit(ripple)],
|
|
207
219
|
})
|
|
208
220
|
|
|
209
221
|
await core.bootstrap()
|