@gravito/launchpad 1.2.0 → 1.2.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @gravito/launchpad
2
2
 
3
+ ## 1.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 905588f: fix: replace insecure Math.random() with crypto.randomUUID() for ID and temporary path generation (CWE-330)
8
+
9
+ ## 1.2.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+ - @gravito/core@1.2.1
15
+ - @gravito/enterprise@1.0.3
16
+ - @gravito/ripple@3.0.1
17
+ - @gravito/stasis@3.0.1
18
+
3
19
  ## 1.2.0
4
20
 
5
21
  ### Minor Changes
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 (_e) {}
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.d.mts CHANGED
@@ -9,6 +9,15 @@ interface MissionProps {
9
9
  branch: string;
10
10
  commitSha: string;
11
11
  }
12
+ /**
13
+ * Mission represents a deployment task for a specific code version.
14
+ *
15
+ * It is a Value Object containing information about the source repository,
16
+ * branch, and commit to be deployed.
17
+ *
18
+ * @public
19
+ * @since 3.0.0
20
+ */
12
21
  declare class Mission extends ValueObject<MissionProps> {
13
22
  get id(): string;
14
23
  get repoUrl(): string;
@@ -28,6 +37,16 @@ declare enum RocketStatus {
28
37
  DECOMMISSIONED = "DECOMMISSIONED"
29
38
  }
30
39
 
40
+ /**
41
+ * Rocket represents a managed application container within Launchpad.
42
+ *
43
+ * It acts as an Aggregate Root in the domain, maintaining its lifecycle state
44
+ * (IDLE, PREPARING, ORBITING, etc.) and emitting domain events when
45
+ * state transitions occur.
46
+ *
47
+ * @public
48
+ * @since 3.0.0
49
+ */
31
50
  declare class Rocket extends AggregateRoot<string> {
32
51
  private _status;
33
52
  private _currentMission;
@@ -140,6 +159,15 @@ interface IRocketRepository {
140
159
  delete(id: string): Promise<void>;
141
160
  }
142
161
 
162
+ /**
163
+ * PayloadInjector is responsible for deploying application code into Rocket containers.
164
+ *
165
+ * It clones the repository, copies files into the container, installs
166
+ * dependencies (using Bun), and starts the application.
167
+ *
168
+ * @public
169
+ * @since 3.0.0
170
+ */
143
171
  declare class PayloadInjector {
144
172
  private docker;
145
173
  private git;
@@ -147,6 +175,16 @@ declare class PayloadInjector {
147
175
  deploy(rocket: Rocket): Promise<void>;
148
176
  }
149
177
 
178
+ /**
179
+ * RefurbishUnit handles the cleaning and restoration of Rocket containers.
180
+ *
181
+ * After a mission is complete, this unit resets the container environment
182
+ * (clearing files, stopping processes) so the container can be returned
183
+ * to the idle pool for future reuse.
184
+ *
185
+ * @public
186
+ * @since 3.0.0
187
+ */
150
188
  declare class RefurbishUnit {
151
189
  private docker;
152
190
  constructor(docker: IDockerAdapter);
@@ -156,6 +194,15 @@ declare class RefurbishUnit {
156
194
  refurbish(rocket: Rocket): Promise<void>;
157
195
  }
158
196
 
197
+ /**
198
+ * PoolManager handles the lifecycle and pooling of Rocket containers.
199
+ *
200
+ * It manages a pool of pre-warmed containers to ensure fast deployment of
201
+ * new missions. It also handles rocket assignment and recycling (refurbishment).
202
+ *
203
+ * @public
204
+ * @since 3.0.0
205
+ */
159
206
  declare class PoolManager {
160
207
  private dockerAdapter;
161
208
  private rocketRepository;
@@ -176,6 +223,15 @@ declare class PoolManager {
176
223
  recycle(missionId: string): Promise<void>;
177
224
  }
178
225
 
226
+ /**
227
+ * MissionControl orchestrates the high-level process of launching missions.
228
+ *
229
+ * it coordinates between the `PoolManager`, `PayloadInjector`, and `DockerAdapter`
230
+ * to deploy code into containers, assign domains, and monitor execution.
231
+ *
232
+ * @public
233
+ * @since 3.0.0
234
+ */
179
235
  declare class MissionControl {
180
236
  private poolManager;
181
237
  private injector;
@@ -186,15 +242,33 @@ declare class MissionControl {
186
242
  }
187
243
 
188
244
  /**
189
- * Gravito Launchpad Orbit
245
+ * LaunchpadOrbit provides automated deployment and preview capabilities for Gravito.
246
+ * It integrates with Docker and GitHub to provide "Preview Deployments" for Pull Requests.
247
+ *
248
+ * @public
190
249
  */
191
250
  declare class LaunchpadOrbit implements GravitoOrbit {
192
251
  private ripple;
252
+ /**
253
+ * Create a new LaunchpadOrbit instance.
254
+ * @param ripple - Ripple instance for real-time telemetry communication.
255
+ */
193
256
  constructor(ripple: OrbitRipple);
257
+ /**
258
+ * Install the Launchpad orbit into PlanetCore.
259
+ * Registers the service provider and sets up webhook routes for deployment.
260
+ *
261
+ * @param core - The PlanetCore instance.
262
+ */
194
263
  install(core: PlanetCore): Promise<void>;
195
264
  }
196
265
  /**
197
- * 一鍵啟動 Launchpad 應用程式
266
+ * Bootstrap the Launchpad application.
267
+ * Initializes PlanetCore with necessary orbits (Cache, Ripple, Launchpad)
268
+ * and returns the configuration for the server entry point.
269
+ *
270
+ * @returns Server configuration object including port and fetch handler.
271
+ * @public
198
272
  */
199
273
  declare function bootstrapLaunchpad(): Promise<{
200
274
  port: number;
package/dist/index.d.ts CHANGED
@@ -9,6 +9,15 @@ interface MissionProps {
9
9
  branch: string;
10
10
  commitSha: string;
11
11
  }
12
+ /**
13
+ * Mission represents a deployment task for a specific code version.
14
+ *
15
+ * It is a Value Object containing information about the source repository,
16
+ * branch, and commit to be deployed.
17
+ *
18
+ * @public
19
+ * @since 3.0.0
20
+ */
12
21
  declare class Mission extends ValueObject<MissionProps> {
13
22
  get id(): string;
14
23
  get repoUrl(): string;
@@ -28,6 +37,16 @@ declare enum RocketStatus {
28
37
  DECOMMISSIONED = "DECOMMISSIONED"
29
38
  }
30
39
 
40
+ /**
41
+ * Rocket represents a managed application container within Launchpad.
42
+ *
43
+ * It acts as an Aggregate Root in the domain, maintaining its lifecycle state
44
+ * (IDLE, PREPARING, ORBITING, etc.) and emitting domain events when
45
+ * state transitions occur.
46
+ *
47
+ * @public
48
+ * @since 3.0.0
49
+ */
31
50
  declare class Rocket extends AggregateRoot<string> {
32
51
  private _status;
33
52
  private _currentMission;
@@ -140,6 +159,15 @@ interface IRocketRepository {
140
159
  delete(id: string): Promise<void>;
141
160
  }
142
161
 
162
+ /**
163
+ * PayloadInjector is responsible for deploying application code into Rocket containers.
164
+ *
165
+ * It clones the repository, copies files into the container, installs
166
+ * dependencies (using Bun), and starts the application.
167
+ *
168
+ * @public
169
+ * @since 3.0.0
170
+ */
143
171
  declare class PayloadInjector {
144
172
  private docker;
145
173
  private git;
@@ -147,6 +175,16 @@ declare class PayloadInjector {
147
175
  deploy(rocket: Rocket): Promise<void>;
148
176
  }
149
177
 
178
+ /**
179
+ * RefurbishUnit handles the cleaning and restoration of Rocket containers.
180
+ *
181
+ * After a mission is complete, this unit resets the container environment
182
+ * (clearing files, stopping processes) so the container can be returned
183
+ * to the idle pool for future reuse.
184
+ *
185
+ * @public
186
+ * @since 3.0.0
187
+ */
150
188
  declare class RefurbishUnit {
151
189
  private docker;
152
190
  constructor(docker: IDockerAdapter);
@@ -156,6 +194,15 @@ declare class RefurbishUnit {
156
194
  refurbish(rocket: Rocket): Promise<void>;
157
195
  }
158
196
 
197
+ /**
198
+ * PoolManager handles the lifecycle and pooling of Rocket containers.
199
+ *
200
+ * It manages a pool of pre-warmed containers to ensure fast deployment of
201
+ * new missions. It also handles rocket assignment and recycling (refurbishment).
202
+ *
203
+ * @public
204
+ * @since 3.0.0
205
+ */
159
206
  declare class PoolManager {
160
207
  private dockerAdapter;
161
208
  private rocketRepository;
@@ -176,6 +223,15 @@ declare class PoolManager {
176
223
  recycle(missionId: string): Promise<void>;
177
224
  }
178
225
 
226
+ /**
227
+ * MissionControl orchestrates the high-level process of launching missions.
228
+ *
229
+ * it coordinates between the `PoolManager`, `PayloadInjector`, and `DockerAdapter`
230
+ * to deploy code into containers, assign domains, and monitor execution.
231
+ *
232
+ * @public
233
+ * @since 3.0.0
234
+ */
179
235
  declare class MissionControl {
180
236
  private poolManager;
181
237
  private injector;
@@ -186,15 +242,33 @@ declare class MissionControl {
186
242
  }
187
243
 
188
244
  /**
189
- * Gravito Launchpad Orbit
245
+ * LaunchpadOrbit provides automated deployment and preview capabilities for Gravito.
246
+ * It integrates with Docker and GitHub to provide "Preview Deployments" for Pull Requests.
247
+ *
248
+ * @public
190
249
  */
191
250
  declare class LaunchpadOrbit implements GravitoOrbit {
192
251
  private ripple;
252
+ /**
253
+ * Create a new LaunchpadOrbit instance.
254
+ * @param ripple - Ripple instance for real-time telemetry communication.
255
+ */
193
256
  constructor(ripple: OrbitRipple);
257
+ /**
258
+ * Install the Launchpad orbit into PlanetCore.
259
+ * Registers the service provider and sets up webhook routes for deployment.
260
+ *
261
+ * @param core - The PlanetCore instance.
262
+ */
194
263
  install(core: PlanetCore): Promise<void>;
195
264
  }
196
265
  /**
197
- * 一鍵啟動 Launchpad 應用程式
266
+ * Bootstrap the Launchpad application.
267
+ * Initializes PlanetCore with necessary orbits (Cache, Ripple, Launchpad)
268
+ * and returns the configuration for the server entry point.
269
+ *
270
+ * @returns Server configuration object including port and fetch handler.
271
+ * @public
198
272
  */
199
273
  declare function bootstrapLaunchpad(): Promise<{
200
274
  port: number;
package/dist/index.js CHANGED
@@ -298,7 +298,7 @@ var PoolManager = class {
298
298
  console.log(`[LaunchPad] \u6B63\u5728\u71B1\u6A5F\uFF0C\u6E96\u5099\u767C\u5C04 ${needed} \u67B6\u65B0\u706B\u7BAD...`);
299
299
  for (let i = 0; i < needed; i++) {
300
300
  const containerId = await this.dockerAdapter.createBaseContainer();
301
- const rocketId = `rocket-${Math.random().toString(36).substring(2, 9)}`;
301
+ const rocketId = `rocket-${crypto.randomUUID()}`;
302
302
  const rocket = new Rocket(rocketId, containerId);
303
303
  await this.rocketRepository.save(rocket);
304
304
  }
@@ -394,7 +394,7 @@ var DockerAdapter = class {
394
394
  baseImage = "oven/bun:1.0-slim";
395
395
  runtime = (0, import_core.getRuntimeAdapter)();
396
396
  async createBaseContainer() {
397
- const rocketId = `rocket-${Math.random().toString(36).substring(2, 9)}`;
397
+ const rocketId = `rocket-${crypto.randomUUID()}`;
398
398
  const proc = this.runtime.spawn([
399
399
  "docker",
400
400
  "run",
@@ -509,7 +509,7 @@ var import_core2 = require("@gravito/core");
509
509
  var ShellGitAdapter = class {
510
510
  baseDir = "/tmp/gravito-launchpad-git";
511
511
  async clone(repoUrl, branch) {
512
- const dirName = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
512
+ const dirName = `${Date.now()}-${crypto.randomUUID()}`;
513
513
  const targetDir = `${this.baseDir}/${dirName}`;
514
514
  await (0, import_promises.mkdir)(this.baseDir, { recursive: true });
515
515
  const runtime = (0, import_core2.getRuntimeAdapter)();
@@ -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());
@@ -708,9 +704,19 @@ var LaunchpadServiceProvider = class extends import_core4.ServiceProvider {
708
704
  }
709
705
  };
710
706
  var LaunchpadOrbit = class {
707
+ /**
708
+ * Create a new LaunchpadOrbit instance.
709
+ * @param ripple - Ripple instance for real-time telemetry communication.
710
+ */
711
711
  constructor(ripple) {
712
712
  this.ripple = ripple;
713
713
  }
714
+ /**
715
+ * Install the Launchpad orbit into PlanetCore.
716
+ * Registers the service provider and sets up webhook routes for deployment.
717
+ *
718
+ * @param core - The PlanetCore instance.
719
+ */
714
720
  async install(core) {
715
721
  core.register(new LaunchpadServiceProvider());
716
722
  core.router.post("/launch", async (c) => {
@@ -784,12 +790,7 @@ async function bootstrapLaunchpad() {
784
790
  PORT: 4e3,
785
791
  CACHE_DRIVER: "file"
786
792
  },
787
- orbits: [
788
- new import_stasis.OrbitCache(),
789
- ripple,
790
- new LaunchpadOrbit(ripple)
791
- // 傳入實例
792
- ]
793
+ orbits: [new import_stasis.OrbitCache(), ripple, new LaunchpadOrbit(ripple)]
793
794
  });
794
795
  await core.bootstrap();
795
796
  const liftoffConfig = core.liftoff();
package/dist/index.mjs CHANGED
@@ -266,7 +266,7 @@ var PoolManager = class {
266
266
  console.log(`[LaunchPad] \u6B63\u5728\u71B1\u6A5F\uFF0C\u6E96\u5099\u767C\u5C04 ${needed} \u67B6\u65B0\u706B\u7BAD...`);
267
267
  for (let i = 0; i < needed; i++) {
268
268
  const containerId = await this.dockerAdapter.createBaseContainer();
269
- const rocketId = `rocket-${Math.random().toString(36).substring(2, 9)}`;
269
+ const rocketId = `rocket-${crypto.randomUUID()}`;
270
270
  const rocket = new Rocket(rocketId, containerId);
271
271
  await this.rocketRepository.save(rocket);
272
272
  }
@@ -362,7 +362,7 @@ var DockerAdapter = class {
362
362
  baseImage = "oven/bun:1.0-slim";
363
363
  runtime = getRuntimeAdapter();
364
364
  async createBaseContainer() {
365
- const rocketId = `rocket-${Math.random().toString(36).substring(2, 9)}`;
365
+ const rocketId = `rocket-${crypto.randomUUID()}`;
366
366
  const proc = this.runtime.spawn([
367
367
  "docker",
368
368
  "run",
@@ -477,7 +477,7 @@ import { getRuntimeAdapter as getRuntimeAdapter2 } from "@gravito/core";
477
477
  var ShellGitAdapter = class {
478
478
  baseDir = "/tmp/gravito-launchpad-git";
479
479
  async clone(repoUrl, branch) {
480
- const dirName = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
480
+ const dirName = `${Date.now()}-${crypto.randomUUID()}`;
481
481
  const targetDir = `${this.baseDir}/${dirName}`;
482
482
  await mkdir(this.baseDir, { recursive: true });
483
483
  const runtime = getRuntimeAdapter2();
@@ -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());
@@ -676,9 +672,19 @@ var LaunchpadServiceProvider = class extends ServiceProvider {
676
672
  }
677
673
  };
678
674
  var LaunchpadOrbit = class {
675
+ /**
676
+ * Create a new LaunchpadOrbit instance.
677
+ * @param ripple - Ripple instance for real-time telemetry communication.
678
+ */
679
679
  constructor(ripple) {
680
680
  this.ripple = ripple;
681
681
  }
682
+ /**
683
+ * Install the Launchpad orbit into PlanetCore.
684
+ * Registers the service provider and sets up webhook routes for deployment.
685
+ *
686
+ * @param core - The PlanetCore instance.
687
+ */
682
688
  async install(core) {
683
689
  core.register(new LaunchpadServiceProvider());
684
690
  core.router.post("/launch", async (c) => {
@@ -752,12 +758,7 @@ async function bootstrapLaunchpad() {
752
758
  PORT: 4e3,
753
759
  CACHE_DRIVER: "file"
754
760
  },
755
- orbits: [
756
- new OrbitCache(),
757
- ripple,
758
- new LaunchpadOrbit(ripple)
759
- // 傳入實例
760
- ]
761
+ orbits: [new OrbitCache(), ripple, new LaunchpadOrbit(ripple)]
761
762
  });
762
763
  await core.bootstrap();
763
764
  const liftoffConfig = core.liftoff();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravito/launchpad",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Container lifecycle management system for flash deployments",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -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,
@@ -26,7 +35,7 @@ export class PoolManager {
26
35
 
27
36
  for (let i = 0; i < needed; i++) {
28
37
  const containerId = await this.dockerAdapter.createBaseContainer()
29
- const rocketId = `rocket-${Math.random().toString(36).substring(2, 9)}`
38
+ const rocketId = `rocket-${crypto.randomUUID()}`
30
39
  const rocket = new Rocket(rocketId, containerId)
31
40
  await this.rocketRepository.save(rocket)
32
41
  }
@@ -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
 
@@ -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()
@@ -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
@@ -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,12 +1,21 @@
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()
7
16
 
8
17
  async createBaseContainer(): Promise<string> {
9
- const rocketId = `rocket-${Math.random().toString(36).substring(2, 9)}`
18
+ const rocketId = `rocket-${crypto.randomUUID()}`
10
19
 
11
20
  const proc = this.runtime.spawn([
12
21
  'docker',
@@ -2,11 +2,20 @@ 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
 
8
17
  async clone(repoUrl: string, branch: string): Promise<string> {
9
- const dirName = `${Date.now()}-${Math.random().toString(36).slice(2)}`
18
+ const dirName = `${Date.now()}-${crypto.randomUUID()}`
10
19
  const targetDir = `${this.baseDir}/${dirName}`
11
20
 
12
21
  await mkdir(this.baseDir, { recursive: true })
@@ -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
- const cacheFromServices = this.core?.services?.get('cache')
30
- if (cacheFromServices) {
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
- * Gravito Launchpad Orbit
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
- // 修正:使用正確的 broadcast 方法
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
- * 一鍵啟動 Launchpad 應用程式
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()