openship 0.1.0 → 0.1.7
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/dist/index.d.ts +1 -0
- package/dist/index.js +5786 -0
- package/dist/server/index.js +324319 -0
- package/dist/server/migrations/0000_init.sql +666 -0
- package/dist/server/migrations/0001_brief_tomorrow_man.sql +47 -0
- package/dist/server/migrations/0002_funny_dazzler.sql +2 -0
- package/dist/server/migrations/0003_third_killer_shrike.sql +1 -0
- package/dist/server/migrations/0004_session_active_org_not_null.sql +10 -0
- package/dist/server/migrations/0005_warm_amazoness.sql +3 -0
- package/dist/server/migrations/0006_lumpy_joystick.sql +1 -0
- package/dist/server/migrations/0007_outgoing_maginty.sql +2 -0
- package/dist/server/migrations/0008_frozen_cutover.sql +3 -0
- package/dist/server/migrations/0009_credits_billing.sql +142 -0
- package/dist/server/migrations/0010_credit_grant_dedupe.sql +14 -0
- package/dist/server/migrations/0011_remove_credit_ledger.sql +23 -0
- package/dist/server/migrations/0012_smart_deploys_and_git_rollback.sql +81 -0
- package/dist/server/migrations/0013_fix_check_run_rollup_unique.sql +38 -0
- package/dist/server/migrations/0014_default_rollback_git.sql +9 -0
- package/dist/server/migrations/0015_billing_idempotency_grants.sql +41 -0
- package/dist/server/migrations/0016_github_auth_high_findings.sql +30 -0
- package/dist/server/migrations/0017_spooky_rumiko_fujikawa.sql +6 -0
- package/dist/server/migrations/0018_calm_shatterstar.sql +1 -0
- package/dist/server/migrations/0019_rename_workspace_install_to_prepare.sql +1 -0
- package/dist/server/migrations/0020_uneven_the_renegades.sql +13 -0
- package/dist/server/migrations/0021_shiny_firestar.sql +2 -0
- package/dist/server/migrations/0022_version_on_success_backfill.sql +6 -0
- package/dist/server/migrations/0023_productive_gorilla_man.sql +17 -0
- package/dist/server/migrations/0024_sleepy_peter_quill.sql +2 -0
- package/dist/server/migrations/0025_smooth_blue_shield.sql +1 -0
- package/dist/server/migrations/0026_mail_backup_source.sql +11 -0
- package/dist/server/migrations/0027_opposite_anthem.sql +6 -0
- package/dist/server/migrations/0028_stale_rogue.sql +18 -0
- package/dist/server/migrations/0029_bouncy_loners.sql +16 -0
- package/dist/server/migrations/0030_bright_darkstar.sql +6 -0
- package/dist/server/migrations/0031_conscious_catseye.sql +13 -0
- package/dist/server/migrations/0032_wet_mimic.sql +51 -0
- package/dist/server/migrations/0033_eminent_molly_hayes.sql +2 -0
- package/dist/server/migrations/meta/0000_snapshot.json +5110 -0
- package/dist/server/migrations/meta/0001_snapshot.json +5257 -0
- package/dist/server/migrations/meta/0002_snapshot.json +5279 -0
- package/dist/server/migrations/meta/0003_snapshot.json +5286 -0
- package/dist/server/migrations/meta/0004_snapshot.json +5286 -0
- package/dist/server/migrations/meta/0005_snapshot.json +5305 -0
- package/dist/server/migrations/meta/0006_snapshot.json +5311 -0
- package/dist/server/migrations/meta/0007_snapshot.json +5323 -0
- package/dist/server/migrations/meta/0016_snapshot.json +6345 -0
- package/dist/server/migrations/meta/0017_snapshot.json +6383 -0
- package/dist/server/migrations/meta/0018_snapshot.json +6390 -0
- package/dist/server/migrations/meta/0019_snapshot.json +6390 -0
- package/dist/server/migrations/meta/0020_snapshot.json +6497 -0
- package/dist/server/migrations/meta/0021_snapshot.json +6509 -0
- package/dist/server/migrations/meta/0022_snapshot.json +6509 -0
- package/dist/server/migrations/meta/0023_snapshot.json +6629 -0
- package/dist/server/migrations/meta/0024_snapshot.json +6641 -0
- package/dist/server/migrations/meta/0025_snapshot.json +6648 -0
- package/dist/server/migrations/meta/0026_snapshot.json +6750 -0
- package/dist/server/migrations/meta/0027_snapshot.json +6757 -0
- package/dist/server/migrations/meta/0028_snapshot.json +6895 -0
- package/dist/server/migrations/meta/0029_snapshot.json +7028 -0
- package/dist/server/migrations/meta/0030_snapshot.json +7066 -0
- package/dist/server/migrations/meta/0031_snapshot.json +7181 -0
- package/dist/server/migrations/meta/0032_snapshot.json +7570 -0
- package/dist/server/migrations/meta/0033_snapshot.json +7597 -0
- package/dist/server/migrations/meta/_journal.json +244 -0
- package/dist/server/pglite/pglite.data +0 -0
- package/dist/server/pglite/pglite.wasm +0 -0
- package/package.json +33 -21
- package/.env.example +0 -22
- package/.nvmrc +0 -1
- package/.prettierrc +0 -7
- package/CONTRIBUTING.md +0 -40
- package/README.md +0 -164
- package/apps/api/.env.example +0 -30
- package/apps/api/Dockerfile +0 -24
- package/apps/api/package.json +0 -37
- package/apps/api/src/app.ts +0 -26
- package/apps/api/src/config/env.ts +0 -39
- package/apps/api/src/config/index.ts +0 -1
- package/apps/api/src/index.ts +0 -8
- package/apps/api/src/middleware/auth.ts +0 -24
- package/apps/api/src/middleware/error-handler.ts +0 -21
- package/apps/api/src/middleware/index.ts +0 -3
- package/apps/api/src/middleware/rate-limiter.ts +0 -26
- package/apps/api/src/modules/auth/auth.controller.ts +0 -26
- package/apps/api/src/modules/auth/auth.routes.ts +0 -10
- package/apps/api/src/modules/auth/auth.schema.ts +0 -12
- package/apps/api/src/modules/auth/auth.service.ts +0 -23
- package/apps/api/src/modules/billing/billing.controller.ts +0 -60
- package/apps/api/src/modules/billing/billing.routes.ts +0 -26
- package/apps/api/src/modules/billing/billing.schema.ts +0 -9
- package/apps/api/src/modules/billing/billing.service.ts +0 -33
- package/apps/api/src/modules/deployments/deployment.controller.ts +0 -35
- package/apps/api/src/modules/deployments/deployment.routes.ts +0 -11
- package/apps/api/src/modules/deployments/deployment.schema.ts +0 -7
- package/apps/api/src/modules/deployments/deployment.service.ts +0 -23
- package/apps/api/src/modules/domains/domain.controller.ts +0 -21
- package/apps/api/src/modules/domains/domain.routes.ts +0 -9
- package/apps/api/src/modules/domains/domain.service.ts +0 -19
- package/apps/api/src/modules/health/health.routes.ts +0 -10
- package/apps/api/src/modules/projects/project.controller.ts +0 -29
- package/apps/api/src/modules/projects/project.routes.ts +0 -10
- package/apps/api/src/modules/projects/project.schema.ts +0 -9
- package/apps/api/src/modules/projects/project.service.ts +0 -23
- package/apps/api/src/modules/webhooks/webhook.controller.ts +0 -22
- package/apps/api/src/modules/webhooks/webhook.routes.ts +0 -12
- package/apps/api/src/modules/webhooks/webhook.service.ts +0 -11
- package/apps/api/tsconfig.json +0 -12
- package/apps/cli/package.json +0 -28
- package/apps/cli/src/commands/deploy.ts +0 -11
- package/apps/cli/src/commands/init.ts +0 -8
- package/apps/cli/src/commands/login.ts +0 -8
- package/apps/cli/src/commands/logs.ts +0 -9
- package/apps/cli/src/index.ts +0 -21
- package/apps/cli/src/lib/api-client.ts +0 -35
- package/apps/cli/tsconfig.json +0 -12
- package/apps/dashboard/Dockerfile +0 -24
- package/apps/dashboard/next.config.mjs +0 -6
- package/apps/dashboard/package.json +0 -28
- package/apps/dashboard/src/app/(auth)/layout.tsx +0 -6
- package/apps/dashboard/src/app/(auth)/login/page.tsx +0 -11
- package/apps/dashboard/src/app/(auth)/register/page.tsx +0 -10
- package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +0 -10
- package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +0 -8
- package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +0 -8
- package/apps/dashboard/src/app/(dashboard)/layout.tsx +0 -37
- package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +0 -8
- package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +0 -8
- package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +0 -8
- package/apps/dashboard/src/app/globals.css +0 -3
- package/apps/dashboard/src/app/layout.tsx +0 -15
- package/apps/dashboard/src/app/page.tsx +0 -6
- package/apps/dashboard/tsconfig.json +0 -11
- package/apps/web/Dockerfile +0 -24
- package/apps/web/next.config.mjs +0 -6
- package/apps/web/package.json +0 -26
- package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
- package/apps/web/src/app/(marketing)/layout.tsx +0 -24
- package/apps/web/src/app/(marketing)/page.tsx +0 -2
- package/apps/web/src/app/(marketing)/pricing/page.tsx +0 -10
- package/apps/web/src/app/globals.css +0 -3
- package/apps/web/src/app/layout.tsx +0 -16
- package/apps/web/src/app/page.tsx +0 -10
- package/apps/web/tsconfig.json +0 -11
- package/docker-compose.yml +0 -87
- package/packages/adapters/package.json +0 -27
- package/packages/adapters/src/base-adapter.ts +0 -49
- package/packages/adapters/src/docker-adapter.ts +0 -43
- package/packages/adapters/src/index.ts +0 -4
- package/packages/adapters/src/oblien-adapter.ts +0 -46
- package/packages/adapters/src/registry.ts +0 -22
- package/packages/adapters/tsconfig.json +0 -9
- package/packages/core/package.json +0 -27
- package/packages/core/src/constants.ts +0 -28
- package/packages/core/src/errors.ts +0 -49
- package/packages/core/src/index.ts +0 -4
- package/packages/core/src/types.ts +0 -47
- package/packages/core/src/utils.ts +0 -35
- package/packages/core/tsconfig.json +0 -9
- package/packages/db/package.json +0 -32
- package/packages/db/prisma/schema.prisma +0 -160
- package/packages/db/src/index.ts +0 -11
- package/packages/db/tsconfig.json +0 -9
- package/packages/ui/package.json +0 -38
- package/packages/ui/src/components/badge.tsx +0 -29
- package/packages/ui/src/components/button.tsx +0 -44
- package/packages/ui/src/components/card.tsx +0 -26
- package/packages/ui/src/components/status-dot.tsx +0 -25
- package/packages/ui/src/globals.css +0 -18
- package/packages/ui/src/index.tsx +0 -8
- package/packages/ui/src/lib/cn.ts +0 -7
- package/packages/ui/tsconfig.json +0 -9
- package/pnpm-workspace.yaml +0 -4
- package/tooling/tsconfig/base.json +0 -19
- package/tooling/tsconfig/nextjs.json +0 -10
- package/tooling/tsconfig/node.json +0 -10
- package/tooling/tsconfig/package.json +0 -7
- package/turbo.json +0 -32
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base adapter interface.
|
|
3
|
-
*
|
|
4
|
-
* Every deployment target (Docker, Oblien, AWS, etc.) must implement this contract.
|
|
5
|
-
* This is the abstraction that makes Openship platform-agnostic.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export interface DeploymentConfig {
|
|
9
|
-
projectId: string;
|
|
10
|
-
branch: string;
|
|
11
|
-
commitSha?: string;
|
|
12
|
-
environment: "production" | "preview";
|
|
13
|
-
envVars?: Record<string, string>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface DeploymentResult {
|
|
17
|
-
id: string;
|
|
18
|
-
url: string;
|
|
19
|
-
status: "queued" | "building" | "deploying" | "ready" | "failed" | "cancelled";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface BuildLog {
|
|
23
|
-
timestamp: string;
|
|
24
|
-
message: string;
|
|
25
|
-
level: "info" | "warn" | "error";
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface DeploymentAdapter {
|
|
29
|
-
/** Human-readable name of the adapter */
|
|
30
|
-
readonly name: string;
|
|
31
|
-
|
|
32
|
-
/** Deploy a project and return the deployment result */
|
|
33
|
-
deploy(config: DeploymentConfig): Promise<DeploymentResult>;
|
|
34
|
-
|
|
35
|
-
/** Get the current status of a deployment */
|
|
36
|
-
getStatus(deploymentId: string): Promise<DeploymentResult>;
|
|
37
|
-
|
|
38
|
-
/** Stream or fetch build/deploy logs */
|
|
39
|
-
getLogs(deploymentId: string): Promise<BuildLog[]>;
|
|
40
|
-
|
|
41
|
-
/** Cancel an in-progress deployment */
|
|
42
|
-
cancel(deploymentId: string): Promise<void>;
|
|
43
|
-
|
|
44
|
-
/** Rollback to a previous deployment */
|
|
45
|
-
rollback(deploymentId: string): Promise<DeploymentResult>;
|
|
46
|
-
|
|
47
|
-
/** Tear down / delete a deployment and its resources */
|
|
48
|
-
destroy(deploymentId: string): Promise<void>;
|
|
49
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { DeploymentAdapter, DeploymentConfig, DeploymentResult, BuildLog } from "./base-adapter";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Docker adapter — used for self-hosted deployments.
|
|
5
|
-
*
|
|
6
|
-
* Builds and runs containers on the host machine using Docker Engine API.
|
|
7
|
-
* This is the default adapter for open-source / self-hosted installations.
|
|
8
|
-
*/
|
|
9
|
-
export class DockerAdapter implements DeploymentAdapter {
|
|
10
|
-
readonly name = "docker";
|
|
11
|
-
|
|
12
|
-
async deploy(config: DeploymentConfig): Promise<DeploymentResult> {
|
|
13
|
-
// TODO: Clone repo, docker build, docker run
|
|
14
|
-
return {
|
|
15
|
-
id: `docker-${Date.now()}`,
|
|
16
|
-
url: `http://localhost:3000`,
|
|
17
|
-
status: "queued",
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async getStatus(deploymentId: string): Promise<DeploymentResult> {
|
|
22
|
-
// TODO: Inspect container status
|
|
23
|
-
return { id: deploymentId, url: "", status: "ready" };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async getLogs(deploymentId: string): Promise<BuildLog[]> {
|
|
27
|
-
// TODO: docker logs
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async cancel(deploymentId: string): Promise<void> {
|
|
32
|
-
// TODO: docker stop
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async rollback(deploymentId: string): Promise<DeploymentResult> {
|
|
36
|
-
// TODO: Restart previous container
|
|
37
|
-
return { id: deploymentId, url: "", status: "ready" };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async destroy(deploymentId: string): Promise<void> {
|
|
41
|
-
// TODO: docker rm -f
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { DeploymentAdapter, DeploymentConfig, DeploymentResult, BuildLog } from "./base-adapter";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Oblien adapter — used for cloud-managed deployments.
|
|
5
|
-
*
|
|
6
|
-
* Communicates with the Oblien infrastructure API to provision and manage
|
|
7
|
-
* containers/VMs for paying cloud users. This adapter is what makes the
|
|
8
|
-
* hosted SaaS version work.
|
|
9
|
-
*/
|
|
10
|
-
export class OblienAdapter implements DeploymentAdapter {
|
|
11
|
-
readonly name = "oblien";
|
|
12
|
-
|
|
13
|
-
constructor(private apiUrl: string, private apiKey: string) {}
|
|
14
|
-
|
|
15
|
-
async deploy(config: DeploymentConfig): Promise<DeploymentResult> {
|
|
16
|
-
// TODO: Call Oblien API to create deployment
|
|
17
|
-
return {
|
|
18
|
-
id: `oblien-${Date.now()}`,
|
|
19
|
-
url: `https://${config.projectId}.openship.cloud`,
|
|
20
|
-
status: "queued",
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async getStatus(deploymentId: string): Promise<DeploymentResult> {
|
|
25
|
-
// TODO: Query Oblien API
|
|
26
|
-
return { id: deploymentId, url: "", status: "ready" };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async getLogs(deploymentId: string): Promise<BuildLog[]> {
|
|
30
|
-
// TODO: Fetch logs from Oblien
|
|
31
|
-
return [];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async cancel(deploymentId: string): Promise<void> {
|
|
35
|
-
// TODO: Cancel via Oblien API
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async rollback(deploymentId: string): Promise<DeploymentResult> {
|
|
39
|
-
// TODO: Rollback via Oblien API
|
|
40
|
-
return { id: deploymentId, url: "", status: "ready" };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async destroy(deploymentId: string): Promise<void> {
|
|
44
|
-
// TODO: Destroy via Oblien API
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { DeploymentAdapter } from "./base-adapter";
|
|
2
|
-
import { DockerAdapter } from "./docker-adapter";
|
|
3
|
-
import { OblienAdapter } from "./oblien-adapter";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Adapter registry — resolves the correct adapter based on config.
|
|
7
|
-
*
|
|
8
|
-
* Self-hosted → DockerAdapter
|
|
9
|
-
* Cloud mode → OblienAdapter
|
|
10
|
-
*/
|
|
11
|
-
export function getAdapter(mode: "docker" | "oblien" = "docker"): DeploymentAdapter {
|
|
12
|
-
switch (mode) {
|
|
13
|
-
case "oblien":
|
|
14
|
-
return new OblienAdapter(
|
|
15
|
-
process.env.OBLIEN_API_URL || "https://api.oblien.com",
|
|
16
|
-
process.env.OBLIEN_API_KEY || "",
|
|
17
|
-
);
|
|
18
|
-
case "docker":
|
|
19
|
-
default:
|
|
20
|
-
return new DockerAdapter();
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "openship-core",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
15
|
-
"dev": "tsup src/index.ts --format esm --dts --watch",
|
|
16
|
-
"lint": "tsc --noEmit",
|
|
17
|
-
"clean": "rm -rf dist .turbo node_modules"
|
|
18
|
-
},
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"zod": "^3.23.0"
|
|
21
|
-
},
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"openship-tsconfig": "workspace:*",
|
|
24
|
-
"tsup": "^8.1.0",
|
|
25
|
-
"typescript": "^5.4.0"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared constants used across the monorepo.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export const APP_NAME = "Openship";
|
|
6
|
-
|
|
7
|
-
export const DEFAULT_PORT = {
|
|
8
|
-
web: 3000,
|
|
9
|
-
dashboard: 3001,
|
|
10
|
-
api: 4000,
|
|
11
|
-
} as const;
|
|
12
|
-
|
|
13
|
-
export const DEPLOYMENT_STATUSES = [
|
|
14
|
-
"queued",
|
|
15
|
-
"building",
|
|
16
|
-
"deploying",
|
|
17
|
-
"ready",
|
|
18
|
-
"failed",
|
|
19
|
-
"cancelled",
|
|
20
|
-
] as const;
|
|
21
|
-
|
|
22
|
-
export const FRAMEWORKS = ["nextjs", "node", "static", "docker"] as const;
|
|
23
|
-
|
|
24
|
-
export const PLANS = {
|
|
25
|
-
free: { name: "Free", price: 0, buildMinutes: 100, bandwidth: 1 },
|
|
26
|
-
pro: { name: "Pro", price: 20, buildMinutes: 1000, bandwidth: 100 },
|
|
27
|
-
team: { name: "Team", price: 50, buildMinutes: 5000, bandwidth: 500 },
|
|
28
|
-
} as const;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared error classes used across the monorepo.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export class AppError extends Error {
|
|
6
|
-
constructor(
|
|
7
|
-
message: string,
|
|
8
|
-
public statusCode: number = 500,
|
|
9
|
-
public code?: string,
|
|
10
|
-
) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = "AppError";
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class NotFoundError extends AppError {
|
|
17
|
-
constructor(resource: string, id?: string) {
|
|
18
|
-
super(id ? `${resource} '${id}' not found` : `${resource} not found`, 404, "NOT_FOUND");
|
|
19
|
-
this.name = "NotFoundError";
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class UnauthorizedError extends AppError {
|
|
24
|
-
constructor(message = "Unauthorized") {
|
|
25
|
-
super(message, 401, "UNAUTHORIZED");
|
|
26
|
-
this.name = "UnauthorizedError";
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class ForbiddenError extends AppError {
|
|
31
|
-
constructor(message = "Forbidden") {
|
|
32
|
-
super(message, 403, "FORBIDDEN");
|
|
33
|
-
this.name = "ForbiddenError";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class ValidationError extends AppError {
|
|
38
|
-
constructor(message: string, public details?: Record<string, string[]>) {
|
|
39
|
-
super(message, 400, "VALIDATION_ERROR");
|
|
40
|
-
this.name = "ValidationError";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export class ConflictError extends AppError {
|
|
45
|
-
constructor(message: string) {
|
|
46
|
-
super(message, 409, "CONFLICT");
|
|
47
|
-
this.name = "ConflictError";
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared TypeScript types used across apps and packages.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/* ---------- Deployment ---------- */
|
|
6
|
-
|
|
7
|
-
export type DeploymentStatus =
|
|
8
|
-
| "queued"
|
|
9
|
-
| "building"
|
|
10
|
-
| "deploying"
|
|
11
|
-
| "ready"
|
|
12
|
-
| "failed"
|
|
13
|
-
| "cancelled";
|
|
14
|
-
|
|
15
|
-
export type Environment = "production" | "preview" | "development";
|
|
16
|
-
|
|
17
|
-
export type Framework = "nextjs" | "node" | "static" | "docker";
|
|
18
|
-
|
|
19
|
-
export type AdapterType = "docker" | "oblien";
|
|
20
|
-
|
|
21
|
-
/* ---------- Billing ---------- */
|
|
22
|
-
|
|
23
|
-
export type PlanId = "free" | "pro" | "team";
|
|
24
|
-
|
|
25
|
-
export type SubscriptionStatus = "active" | "canceled" | "past_due";
|
|
26
|
-
|
|
27
|
-
export type UsageMetric = "build_minutes" | "bandwidth_gb" | "deployments";
|
|
28
|
-
|
|
29
|
-
/* ---------- Auth ---------- */
|
|
30
|
-
|
|
31
|
-
export type UserRole = "user" | "admin";
|
|
32
|
-
|
|
33
|
-
export type TeamRole = "owner" | "admin" | "member";
|
|
34
|
-
|
|
35
|
-
/* ---------- API Responses ---------- */
|
|
36
|
-
|
|
37
|
-
export interface ApiResponse<T = unknown> {
|
|
38
|
-
data?: T;
|
|
39
|
-
error?: string;
|
|
40
|
-
message?: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
|
|
44
|
-
total: number;
|
|
45
|
-
page: number;
|
|
46
|
-
perPage: number;
|
|
47
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared utility functions.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/** Generate a URL-safe slug from a string */
|
|
6
|
-
export function slugify(text: string): string {
|
|
7
|
-
return text
|
|
8
|
-
.toLowerCase()
|
|
9
|
-
.replace(/[^\w\s-]/g, "")
|
|
10
|
-
.replace(/[\s_]+/g, "-")
|
|
11
|
-
.replace(/^-+|-+$/g, "")
|
|
12
|
-
.slice(0, 100);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** Format bytes to human-readable string */
|
|
16
|
-
export function formatBytes(bytes: number, decimals = 2): string {
|
|
17
|
-
if (bytes === 0) return "0 B";
|
|
18
|
-
const k = 1024;
|
|
19
|
-
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
20
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
21
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${sizes[i]}`;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Format duration in seconds to human-readable string */
|
|
25
|
-
export function formatDuration(seconds: number): string {
|
|
26
|
-
if (seconds < 60) return `${seconds}s`;
|
|
27
|
-
const m = Math.floor(seconds / 60);
|
|
28
|
-
const s = seconds % 60;
|
|
29
|
-
return s > 0 ? `${m}m ${s}s` : `${m}m`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Sleep for a given number of milliseconds */
|
|
33
|
-
export function sleep(ms: number): Promise<void> {
|
|
34
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
35
|
-
}
|
package/packages/db/package.json
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "openship-db",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
15
|
-
"dev": "tsup src/index.ts --format esm --dts --watch",
|
|
16
|
-
"lint": "tsc --noEmit",
|
|
17
|
-
"db:generate": "prisma generate",
|
|
18
|
-
"db:push": "prisma db push",
|
|
19
|
-
"db:migrate": "prisma migrate dev",
|
|
20
|
-
"db:studio": "prisma studio",
|
|
21
|
-
"clean": "rm -rf dist .turbo node_modules"
|
|
22
|
-
},
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"@prisma/client": "^5.14.0"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"openship-tsconfig": "workspace:*",
|
|
28
|
-
"prisma": "^5.14.0",
|
|
29
|
-
"tsup": "^8.1.0",
|
|
30
|
-
"typescript": "^5.4.0"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
// Prisma Schema for Openship
|
|
2
|
-
// SQLite for local/self-hosted · Postgres for cloud
|
|
3
|
-
// Change the datasource provider as needed.
|
|
4
|
-
|
|
5
|
-
generator client {
|
|
6
|
-
provider = "prisma-client-js"
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
datasource db {
|
|
10
|
-
provider = "sqlite" // Switch to "postgresql" for cloud
|
|
11
|
-
url = env("DATABASE_URL")
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// ─── Auth ────────────────────────────────────────────────────────────────────
|
|
15
|
-
|
|
16
|
-
model User {
|
|
17
|
-
id String @id @default(cuid())
|
|
18
|
-
email String @unique
|
|
19
|
-
name String?
|
|
20
|
-
passwordHash String
|
|
21
|
-
avatarUrl String?
|
|
22
|
-
role String @default("user") // user | admin
|
|
23
|
-
createdAt DateTime @default(now())
|
|
24
|
-
updatedAt DateTime @updatedAt
|
|
25
|
-
|
|
26
|
-
projects Project[]
|
|
27
|
-
teams TeamMember[]
|
|
28
|
-
subscription Subscription?
|
|
29
|
-
apiTokens ApiToken[]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
model ApiToken {
|
|
33
|
-
id String @id @default(cuid())
|
|
34
|
-
name String
|
|
35
|
-
token String @unique
|
|
36
|
-
userId String
|
|
37
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
38
|
-
expiresAt DateTime?
|
|
39
|
-
createdAt DateTime @default(now())
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// ─── Teams ───────────────────────────────────────────────────────────────────
|
|
43
|
-
|
|
44
|
-
model Team {
|
|
45
|
-
id String @id @default(cuid())
|
|
46
|
-
name String
|
|
47
|
-
slug String @unique
|
|
48
|
-
createdAt DateTime @default(now())
|
|
49
|
-
updatedAt DateTime @updatedAt
|
|
50
|
-
|
|
51
|
-
members TeamMember[]
|
|
52
|
-
projects Project[]
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
model TeamMember {
|
|
56
|
-
id String @id @default(cuid())
|
|
57
|
-
role String @default("member") // owner | admin | member
|
|
58
|
-
userId String
|
|
59
|
-
teamId String
|
|
60
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
61
|
-
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
62
|
-
|
|
63
|
-
@@unique([userId, teamId])
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ─── Projects ────────────────────────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
model Project {
|
|
69
|
-
id String @id @default(cuid())
|
|
70
|
-
name String
|
|
71
|
-
slug String
|
|
72
|
-
repoUrl String?
|
|
73
|
-
framework String? // nextjs | node | static | docker
|
|
74
|
-
rootDir String @default("/")
|
|
75
|
-
buildCmd String?
|
|
76
|
-
outputDir String?
|
|
77
|
-
createdAt DateTime @default(now())
|
|
78
|
-
updatedAt DateTime @updatedAt
|
|
79
|
-
|
|
80
|
-
userId String?
|
|
81
|
-
user User? @relation(fields: [userId], references: [id])
|
|
82
|
-
teamId String?
|
|
83
|
-
team Team? @relation(fields: [teamId], references: [id])
|
|
84
|
-
|
|
85
|
-
deployments Deployment[]
|
|
86
|
-
domains Domain[]
|
|
87
|
-
envVars EnvVar[]
|
|
88
|
-
|
|
89
|
-
@@unique([slug, teamId])
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
model EnvVar {
|
|
93
|
-
id String @id @default(cuid())
|
|
94
|
-
key String
|
|
95
|
-
value String
|
|
96
|
-
target String @default("production") // production | preview | development
|
|
97
|
-
projectId String
|
|
98
|
-
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
99
|
-
|
|
100
|
-
@@unique([key, target, projectId])
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// ─── Deployments ─────────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
model Deployment {
|
|
106
|
-
id String @id @default(cuid())
|
|
107
|
-
status String @default("queued") // queued | building | deploying | ready | failed | cancelled
|
|
108
|
-
environment String @default("production") // production | preview
|
|
109
|
-
branch String @default("main")
|
|
110
|
-
commitSha String?
|
|
111
|
-
commitMsg String?
|
|
112
|
-
url String?
|
|
113
|
-
buildLogs String? // stored as text; could be moved to object storage
|
|
114
|
-
duration Int? // build duration in seconds
|
|
115
|
-
createdAt DateTime @default(now())
|
|
116
|
-
updatedAt DateTime @updatedAt
|
|
117
|
-
|
|
118
|
-
projectId String
|
|
119
|
-
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// ─── Domains ─────────────────────────────────────────────────────────────────
|
|
123
|
-
|
|
124
|
-
model Domain {
|
|
125
|
-
id String @id @default(cuid())
|
|
126
|
-
domain String @unique
|
|
127
|
-
verified Boolean @default(false)
|
|
128
|
-
sslStatus String @default("pending") // pending | active | failed
|
|
129
|
-
createdAt DateTime @default(now())
|
|
130
|
-
|
|
131
|
-
projectId String
|
|
132
|
-
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// ─── Billing (Cloud only) ────────────────────────────────────────────────────
|
|
136
|
-
|
|
137
|
-
model Subscription {
|
|
138
|
-
id String @id @default(cuid())
|
|
139
|
-
plan String @default("free") // free | pro | team
|
|
140
|
-
status String @default("active") // active | canceled | past_due
|
|
141
|
-
stripeCustomerId String?
|
|
142
|
-
stripeSubId String?
|
|
143
|
-
currentPeriodStart DateTime?
|
|
144
|
-
currentPeriodEnd DateTime?
|
|
145
|
-
createdAt DateTime @default(now())
|
|
146
|
-
updatedAt DateTime @updatedAt
|
|
147
|
-
|
|
148
|
-
userId String @unique
|
|
149
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
model UsageRecord {
|
|
153
|
-
id String @id @default(cuid())
|
|
154
|
-
metric String // build_minutes | bandwidth_gb | deployments
|
|
155
|
-
quantity Float
|
|
156
|
-
period String // "2026-03" (year-month)
|
|
157
|
-
createdAt DateTime @default(now())
|
|
158
|
-
|
|
159
|
-
userId String
|
|
160
|
-
}
|
package/packages/db/src/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { PrismaClient } from "@prisma/client";
|
|
2
|
-
|
|
3
|
-
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };
|
|
4
|
-
|
|
5
|
-
export const db = globalForPrisma.prisma ?? new PrismaClient();
|
|
6
|
-
|
|
7
|
-
if (process.env.NODE_ENV !== "production") {
|
|
8
|
-
globalForPrisma.prisma = db;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export * from "@prisma/client";
|
package/packages/ui/package.json
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "openship-ui",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts"
|
|
11
|
-
},
|
|
12
|
-
"./globals.css": "./src/globals.css"
|
|
13
|
-
},
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "tsup src/index.tsx --format esm --dts --clean --external react --external react-dom",
|
|
16
|
-
"dev": "tsup src/index.tsx --format esm --dts --watch --external react --external react-dom",
|
|
17
|
-
"lint": "tsc --noEmit",
|
|
18
|
-
"clean": "rm -rf dist .turbo node_modules"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"class-variance-authority": "^0.7.0",
|
|
22
|
-
"clsx": "^2.1.0",
|
|
23
|
-
"tailwind-merge": "^2.3.0"
|
|
24
|
-
},
|
|
25
|
-
"peerDependencies": {
|
|
26
|
-
"react": "^18.0.0",
|
|
27
|
-
"react-dom": "^18.0.0"
|
|
28
|
-
},
|
|
29
|
-
"devDependencies": {
|
|
30
|
-
"openship-tsconfig": "workspace:*",
|
|
31
|
-
"@types/react": "^18.3.0",
|
|
32
|
-
"@types/react-dom": "^18.3.0",
|
|
33
|
-
"react": "^18.3.0",
|
|
34
|
-
"react-dom": "^18.3.0",
|
|
35
|
-
"tsup": "^8.1.0",
|
|
36
|
-
"typescript": "^5.4.0"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
import { cn } from "../lib/cn";
|
|
4
|
-
|
|
5
|
-
const badgeVariants = cva(
|
|
6
|
-
"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium",
|
|
7
|
-
{
|
|
8
|
-
variants: {
|
|
9
|
-
variant: {
|
|
10
|
-
default: "bg-primary/10 text-primary",
|
|
11
|
-
success: "bg-green-100 text-green-800",
|
|
12
|
-
warning: "bg-yellow-100 text-yellow-800",
|
|
13
|
-
error: "bg-red-100 text-red-800",
|
|
14
|
-
muted: "bg-muted text-muted-foreground",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
defaultVariants: {
|
|
18
|
-
variant: "default",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
export interface BadgeProps
|
|
24
|
-
extends React.HTMLAttributes<HTMLSpanElement>,
|
|
25
|
-
VariantProps<typeof badgeVariants> {}
|
|
26
|
-
|
|
27
|
-
export function Badge({ className, variant, ...props }: BadgeProps) {
|
|
28
|
-
return <span className={cn(badgeVariants({ variant }), className)} {...props} />;
|
|
29
|
-
}
|