@relesio/cli 0.2.6
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/README.md +224 -0
- package/bin/relesio.js +4 -0
- package/dist/commands/auth/index.d.ts +2 -0
- package/dist/commands/auth/index.js +9 -0
- package/dist/commands/auth/login.d.ts +2 -0
- package/dist/commands/auth/login.js +82 -0
- package/dist/commands/auth/logout.d.ts +2 -0
- package/dist/commands/auth/logout.js +25 -0
- package/dist/commands/auth/status.d.ts +2 -0
- package/dist/commands/auth/status.js +35 -0
- package/dist/commands/deploy.d.ts +2 -0
- package/dist/commands/deploy.js +293 -0
- package/dist/commands/organizations/index.d.ts +2 -0
- package/dist/commands/organizations/index.js +8 -0
- package/dist/commands/organizations/list.d.ts +2 -0
- package/dist/commands/organizations/list.js +54 -0
- package/dist/commands/organizations/set.d.ts +2 -0
- package/dist/commands/organizations/set.js +34 -0
- package/dist/commands/projects/index.d.ts +2 -0
- package/dist/commands/projects/index.js +6 -0
- package/dist/commands/projects/list.d.ts +2 -0
- package/dist/commands/projects/list.js +49 -0
- package/dist/commands/rollback.d.ts +2 -0
- package/dist/commands/rollback.js +119 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +59 -0
- package/dist/commands/team/get.d.ts +2 -0
- package/dist/commands/team/get.js +34 -0
- package/dist/commands/team/index.d.ts +2 -0
- package/dist/commands/team/index.js +7 -0
- package/dist/commands/team/list.d.ts +2 -0
- package/dist/commands/team/list.js +46 -0
- package/dist/commands/upload.d.ts +2 -0
- package/dist/commands/upload.js +365 -0
- package/dist/commands/versions/index.d.ts +2 -0
- package/dist/commands/versions/index.js +6 -0
- package/dist/commands/versions/list.d.ts +2 -0
- package/dist/commands/versions/list.js +51 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +52 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +90 -0
- package/dist/lib/api/client.d.ts +32 -0
- package/dist/lib/api/client.js +187 -0
- package/dist/lib/api/deployments.d.ts +122 -0
- package/dist/lib/api/deployments.js +55 -0
- package/dist/lib/api/organizations.d.ts +27 -0
- package/dist/lib/api/organizations.js +37 -0
- package/dist/lib/api/projects.d.ts +38 -0
- package/dist/lib/api/projects.js +34 -0
- package/dist/lib/api/teams.d.ts +15 -0
- package/dist/lib/api/teams.js +44 -0
- package/dist/lib/api/types.d.ts +89 -0
- package/dist/lib/api/types.js +2 -0
- package/dist/lib/api/versions.d.ts +140 -0
- package/dist/lib/api/versions.js +53 -0
- package/dist/lib/config/manager.d.ts +35 -0
- package/dist/lib/config/manager.js +78 -0
- package/dist/lib/config/types.d.ts +15 -0
- package/dist/lib/config/types.js +15 -0
- package/dist/lib/errors/handler.d.ts +1 -0
- package/dist/lib/errors/handler.js +75 -0
- package/dist/lib/errors/types.d.ts +19 -0
- package/dist/lib/errors/types.js +34 -0
- package/dist/lib/files/scanner.d.ts +23 -0
- package/dist/lib/files/scanner.js +81 -0
- package/dist/lib/git/metadata.d.ts +31 -0
- package/dist/lib/git/metadata.js +90 -0
- package/dist/lib/output/colors.d.ts +14 -0
- package/dist/lib/output/colors.js +23 -0
- package/dist/lib/output/formatter.d.ts +2 -0
- package/dist/lib/output/formatter.js +7 -0
- package/dist/lib/output/table.d.ts +7 -0
- package/dist/lib/output/table.js +64 -0
- package/package.json +58 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const { version } = require("../package.json");
|
|
6
|
+
import { authCommand } from "./commands/auth/index.js";
|
|
7
|
+
import { organizationsCommand } from "./commands/organizations/index.js";
|
|
8
|
+
import { teamCommand } from "./commands/team/index.js";
|
|
9
|
+
import { whoamiCommand } from "./commands/whoami.js";
|
|
10
|
+
import { projectsCommand } from "./commands/projects/index.js";
|
|
11
|
+
import { versionsCommand } from "./commands/versions/index.js";
|
|
12
|
+
import { uploadCommand } from "./commands/upload.js";
|
|
13
|
+
import { deployCommand } from "./commands/deploy.js";
|
|
14
|
+
import { rollbackCommand } from "./commands/rollback.js";
|
|
15
|
+
import { statusCommand } from "./commands/status.js";
|
|
16
|
+
import { handleError } from "./lib/errors/handler.js";
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name("relesio")
|
|
20
|
+
.description("CLI tool for Relesio - Modern Micro-Frontend Hosting")
|
|
21
|
+
.version(version)
|
|
22
|
+
.option("--org <org-id>", "Override organization context (ID or slug)")
|
|
23
|
+
.addHelpText("after", `
|
|
24
|
+
Examples:
|
|
25
|
+
Authentication:
|
|
26
|
+
$ relesio auth login --token rls_...
|
|
27
|
+
$ relesio auth status
|
|
28
|
+
$ relesio auth logout
|
|
29
|
+
|
|
30
|
+
Organizations:
|
|
31
|
+
$ relesio organizations list
|
|
32
|
+
$ relesio organizations set <org-id>
|
|
33
|
+
|
|
34
|
+
Projects & Versions:
|
|
35
|
+
$ relesio projects list
|
|
36
|
+
$ relesio projects list --org my-org-slug
|
|
37
|
+
$ relesio versions list <project-slug>
|
|
38
|
+
$ relesio status <project-slug>
|
|
39
|
+
|
|
40
|
+
Upload & Deployment:
|
|
41
|
+
$ relesio upload ./dist --project my-app --version 1.0.0
|
|
42
|
+
$ relesio upload ./build -p my-app -v 1.0.1 --require-clean
|
|
43
|
+
$ relesio deploy <project-slug> [version] --env production
|
|
44
|
+
$ relesio deploy <project-slug> --latest --env staging
|
|
45
|
+
$ relesio rollback <project-slug> --env production
|
|
46
|
+
|
|
47
|
+
Teams:
|
|
48
|
+
$ relesio team list
|
|
49
|
+
$ relesio team get <teamId>
|
|
50
|
+
|
|
51
|
+
Environment Variables:
|
|
52
|
+
RELESIO_API_TOKEN API authentication token (starts with rls_)
|
|
53
|
+
RELESIO_API_URL API base URL (default: https://api.relesio.com)
|
|
54
|
+
RELESIO_ORG_ID Override organization context
|
|
55
|
+
DEBUG Enable debug output
|
|
56
|
+
|
|
57
|
+
Organization Context Priority:
|
|
58
|
+
1. --org flag (highest priority)
|
|
59
|
+
2. RELESIO_ORG_ID environment variable
|
|
60
|
+
3. Active organization from user session (default)
|
|
61
|
+
`);
|
|
62
|
+
// Add command groups
|
|
63
|
+
program.addCommand(authCommand);
|
|
64
|
+
program.addCommand(organizationsCommand);
|
|
65
|
+
program.addCommand(teamCommand);
|
|
66
|
+
program.addCommand(whoamiCommand);
|
|
67
|
+
program.addCommand(projectsCommand);
|
|
68
|
+
program.addCommand(versionsCommand);
|
|
69
|
+
program.addCommand(uploadCommand);
|
|
70
|
+
program.addCommand(deployCommand);
|
|
71
|
+
program.addCommand(rollbackCommand);
|
|
72
|
+
program.addCommand(statusCommand);
|
|
73
|
+
// Additional global options
|
|
74
|
+
program.option("--json", "Output as JSON");
|
|
75
|
+
program.option("--no-color", "Disable colored output");
|
|
76
|
+
// Error handling
|
|
77
|
+
program.exitOverride((err) => {
|
|
78
|
+
// Allow help to work normally
|
|
79
|
+
if (err.code === "commander.help" ||
|
|
80
|
+
err.code === "commander.helpDisplayed") {
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
if (err.code === "commander.version") {
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
// Handle other commander errors
|
|
87
|
+
handleError(err);
|
|
88
|
+
});
|
|
89
|
+
// Parse and execute
|
|
90
|
+
program.parseAsync(process.argv).catch(handleError);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RequestOptions } from "./types.js";
|
|
2
|
+
export declare class APIError extends Error {
|
|
3
|
+
statusCode: number;
|
|
4
|
+
response?: unknown | undefined;
|
|
5
|
+
constructor(message: string, statusCode: number, response?: unknown | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare class RelesioAPIClient {
|
|
8
|
+
private baseURL;
|
|
9
|
+
private token;
|
|
10
|
+
constructor(baseURL: string, token?: string | null);
|
|
11
|
+
setToken(token: string): void;
|
|
12
|
+
private buildURL;
|
|
13
|
+
private getHeaders;
|
|
14
|
+
/**
|
|
15
|
+
* Get organization ID from priority:
|
|
16
|
+
* 1. Explicit orgId parameter (--org flag)
|
|
17
|
+
* 2. RELESIO_ORG_ID env var
|
|
18
|
+
* 3. Active org from config
|
|
19
|
+
*/
|
|
20
|
+
private getOrganizationContext;
|
|
21
|
+
/**
|
|
22
|
+
* Add organization context header if available
|
|
23
|
+
*/
|
|
24
|
+
private withOrgContext;
|
|
25
|
+
request<T = unknown>(method: "GET" | "POST" | "PATCH" | "DELETE" | "PUT", endpoint: string, options?: RequestOptions & {
|
|
26
|
+
body?: unknown;
|
|
27
|
+
}): Promise<T>;
|
|
28
|
+
get<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T>;
|
|
29
|
+
post<T = unknown>(endpoint: string, body?: unknown, options?: RequestOptions): Promise<T>;
|
|
30
|
+
patch<T = unknown>(endpoint: string, body?: unknown, options?: RequestOptions): Promise<T>;
|
|
31
|
+
delete<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { request } from "undici";
|
|
2
|
+
import { ConfigManager } from "../config/manager.js";
|
|
3
|
+
export class APIError extends Error {
|
|
4
|
+
statusCode;
|
|
5
|
+
response;
|
|
6
|
+
constructor(message, statusCode, response) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.response = response;
|
|
10
|
+
this.name = "APIError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class RelesioAPIClient {
|
|
14
|
+
baseURL;
|
|
15
|
+
token;
|
|
16
|
+
constructor(baseURL, token = null) {
|
|
17
|
+
this.baseURL = baseURL;
|
|
18
|
+
this.token = token;
|
|
19
|
+
// Ensure baseURL doesn't end with slash
|
|
20
|
+
this.baseURL = baseURL.replace(/\/$/, "");
|
|
21
|
+
}
|
|
22
|
+
setToken(token) {
|
|
23
|
+
this.token = token;
|
|
24
|
+
}
|
|
25
|
+
buildURL(endpoint, query) {
|
|
26
|
+
// Ensure endpoint starts with slash
|
|
27
|
+
const path = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
28
|
+
const url = `${this.baseURL}${path}`;
|
|
29
|
+
if (!query || Object.keys(query).length === 0) {
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
const params = new URLSearchParams();
|
|
33
|
+
for (const [key, value] of Object.entries(query)) {
|
|
34
|
+
if (value !== undefined) {
|
|
35
|
+
params.append(key, String(value));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return `${url}?${params.toString()}`;
|
|
39
|
+
}
|
|
40
|
+
getHeaders(additionalHeaders) {
|
|
41
|
+
const headers = {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
"User-Agent": "relesio-cli/0.1.0",
|
|
44
|
+
...additionalHeaders
|
|
45
|
+
};
|
|
46
|
+
// Better Auth requires x-api-key header (not Authorization)
|
|
47
|
+
if (this.token) {
|
|
48
|
+
headers["x-api-key"] = this.token;
|
|
49
|
+
}
|
|
50
|
+
return headers;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get organization ID from priority:
|
|
54
|
+
* 1. Explicit orgId parameter (--org flag)
|
|
55
|
+
* 2. RELESIO_ORG_ID env var
|
|
56
|
+
* 3. Active org from config
|
|
57
|
+
*/
|
|
58
|
+
getOrganizationContext(explicitOrgId) {
|
|
59
|
+
// Priority 1: Explicit parameter
|
|
60
|
+
if (explicitOrgId) {
|
|
61
|
+
return explicitOrgId;
|
|
62
|
+
}
|
|
63
|
+
// Priority 2: Environment variable
|
|
64
|
+
if (process.env.RELESIO_ORG_ID) {
|
|
65
|
+
return process.env.RELESIO_ORG_ID;
|
|
66
|
+
}
|
|
67
|
+
// Priority 3: Active org from config
|
|
68
|
+
const config = ConfigManager.load();
|
|
69
|
+
return config.activeOrganizationId || null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Add organization context header if available
|
|
73
|
+
*/
|
|
74
|
+
withOrgContext(orgId) {
|
|
75
|
+
const resolvedOrgId = this.getOrganizationContext(orgId);
|
|
76
|
+
if (!resolvedOrgId) {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
return { "x-organization-id": resolvedOrgId };
|
|
80
|
+
}
|
|
81
|
+
async request(method, endpoint, options) {
|
|
82
|
+
const url = this.buildURL(endpoint, options?.query);
|
|
83
|
+
const orgContextHeaders = this.withOrgContext(options?.orgId);
|
|
84
|
+
const headers = this.getHeaders({
|
|
85
|
+
...orgContextHeaders,
|
|
86
|
+
...options?.headers
|
|
87
|
+
});
|
|
88
|
+
// Debug logging
|
|
89
|
+
if (process.env.DEBUG) {
|
|
90
|
+
console.error(`\n[DEBUG] HTTP Request:`);
|
|
91
|
+
console.error(` Method: ${method}`);
|
|
92
|
+
console.error(` URL: ${url}`);
|
|
93
|
+
console.error(` Headers:`, {
|
|
94
|
+
...headers,
|
|
95
|
+
"x-api-key": headers["x-api-key"]
|
|
96
|
+
? `${headers["x-api-key"].substring(0, 15)}...`
|
|
97
|
+
: undefined
|
|
98
|
+
});
|
|
99
|
+
if (options?.body) {
|
|
100
|
+
console.error(` Body:`, JSON.stringify(options.body, null, 2));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const response = await request(url, {
|
|
105
|
+
method: method,
|
|
106
|
+
headers,
|
|
107
|
+
body: options?.body ? JSON.stringify(options.body) : undefined,
|
|
108
|
+
bodyTimeout: options?.timeout || 60000, // Increased to 60s for slower connections
|
|
109
|
+
headersTimeout: options?.timeout || 60000
|
|
110
|
+
});
|
|
111
|
+
if (process.env.DEBUG) {
|
|
112
|
+
console.error(`\n[DEBUG] HTTP Response:`);
|
|
113
|
+
console.error(` Status: ${response.statusCode}`);
|
|
114
|
+
console.error(` Headers:`, response.headers);
|
|
115
|
+
}
|
|
116
|
+
const contentType = response.headers["content-type"];
|
|
117
|
+
const isJSON = contentType?.includes("application/json");
|
|
118
|
+
let data;
|
|
119
|
+
if (isJSON) {
|
|
120
|
+
const text = await response.body.text();
|
|
121
|
+
if (process.env.DEBUG) {
|
|
122
|
+
console.error(` Body (raw):`, text.substring(0, 500));
|
|
123
|
+
}
|
|
124
|
+
data = text ? JSON.parse(text) : null;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
data = await response.body.text();
|
|
128
|
+
if (process.env.DEBUG) {
|
|
129
|
+
console.error(` Body (text):`, String(data).substring(0, 500));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (process.env.DEBUG) {
|
|
133
|
+
console.error(` Parsed data:`, JSON.stringify(data, null, 2).substring(0, 500));
|
|
134
|
+
}
|
|
135
|
+
// Handle error responses
|
|
136
|
+
if (response.statusCode >= 400) {
|
|
137
|
+
const err = data;
|
|
138
|
+
const errorMessage = err?.message ?? err?.error ?? `HTTP ${response.statusCode}`;
|
|
139
|
+
throw new APIError(errorMessage, response.statusCode, data);
|
|
140
|
+
}
|
|
141
|
+
// Return the data property if it exists (standard API response), otherwise return the full response
|
|
142
|
+
if (options?.raw) {
|
|
143
|
+
return data;
|
|
144
|
+
}
|
|
145
|
+
const responseData = data;
|
|
146
|
+
return (responseData?.data ?? data);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (error instanceof APIError) {
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
// Network or other errors
|
|
153
|
+
if (error instanceof Error) {
|
|
154
|
+
if (process.env.DEBUG) {
|
|
155
|
+
console.error(`\n[DEBUG] Request Error:`);
|
|
156
|
+
console.error(` Message: ${error.message}`);
|
|
157
|
+
console.error(` Name: ${error.name}`);
|
|
158
|
+
console.error(` Stack:`, error.stack);
|
|
159
|
+
console.error(` Error object:`, error);
|
|
160
|
+
}
|
|
161
|
+
throw new APIError(`Request failed: ${error.message}`, 0, {
|
|
162
|
+
originalError: error.message,
|
|
163
|
+
errorName: error.name,
|
|
164
|
+
errorStack: error.stack
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (process.env.DEBUG) {
|
|
168
|
+
console.error(`\n[DEBUG] Unknown error type:`, error);
|
|
169
|
+
}
|
|
170
|
+
throw new APIError("Unknown error occurred", 0, {
|
|
171
|
+
unknownError: String(error)
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async get(endpoint, options) {
|
|
176
|
+
return this.request("GET", endpoint, options);
|
|
177
|
+
}
|
|
178
|
+
async post(endpoint, body, options) {
|
|
179
|
+
return this.request("POST", endpoint, { ...options, body });
|
|
180
|
+
}
|
|
181
|
+
async patch(endpoint, body, options) {
|
|
182
|
+
return this.request("PATCH", endpoint, { ...options, body });
|
|
183
|
+
}
|
|
184
|
+
async delete(endpoint, options) {
|
|
185
|
+
return this.request("DELETE", endpoint, options);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { RelesioAPIClient } from "./client.js";
|
|
2
|
+
export interface Environment {
|
|
3
|
+
id: string;
|
|
4
|
+
organizationId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
isProduction: boolean;
|
|
8
|
+
protected: boolean;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
updatedAt: string;
|
|
11
|
+
}
|
|
12
|
+
export interface Deployment {
|
|
13
|
+
id: string;
|
|
14
|
+
environmentId: string;
|
|
15
|
+
versionId: string;
|
|
16
|
+
semanticVersion?: string | null;
|
|
17
|
+
deployedBy: string;
|
|
18
|
+
deployedByType: "user" | "api_token" | "service_account";
|
|
19
|
+
deployedAt: string;
|
|
20
|
+
deploymentType: "deploy" | "rollback";
|
|
21
|
+
previousVersionId?: string;
|
|
22
|
+
gitSha?: string;
|
|
23
|
+
gitBranch?: string;
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
export type DeploymentWithVersion = Deployment;
|
|
27
|
+
export interface DeploymentHistoryItem {
|
|
28
|
+
deploymentId: string;
|
|
29
|
+
versionId: string;
|
|
30
|
+
semanticVersion?: string | null;
|
|
31
|
+
gitSha?: string | null;
|
|
32
|
+
gitBranch?: string | null;
|
|
33
|
+
deployedAt: string;
|
|
34
|
+
deployedBy: string;
|
|
35
|
+
deployedByType: "user" | "api_token";
|
|
36
|
+
deploymentType: "deploy" | "rollback";
|
|
37
|
+
metadata?: Record<string, unknown> | null;
|
|
38
|
+
}
|
|
39
|
+
export interface EnvironmentWithDeployment extends Environment {
|
|
40
|
+
currentDeployment: {
|
|
41
|
+
deploymentId: string;
|
|
42
|
+
versionId: string;
|
|
43
|
+
semanticVersion?: string | null;
|
|
44
|
+
deployedAt: string;
|
|
45
|
+
deployedBy: string;
|
|
46
|
+
version?: string;
|
|
47
|
+
deploymentType?: string;
|
|
48
|
+
gitSha?: string;
|
|
49
|
+
gitBranch?: string;
|
|
50
|
+
} | null;
|
|
51
|
+
}
|
|
52
|
+
export interface CreateDeploymentInput {
|
|
53
|
+
versionId: string;
|
|
54
|
+
projectId: string;
|
|
55
|
+
metadata?: Record<string, unknown>;
|
|
56
|
+
}
|
|
57
|
+
export interface CreateDeploymentResponse {
|
|
58
|
+
deployment: {
|
|
59
|
+
id: string;
|
|
60
|
+
environmentId: string;
|
|
61
|
+
versionId: string;
|
|
62
|
+
version: string;
|
|
63
|
+
deployedAt: string;
|
|
64
|
+
};
|
|
65
|
+
url: string;
|
|
66
|
+
message: string;
|
|
67
|
+
}
|
|
68
|
+
export interface RollbackResponse {
|
|
69
|
+
success: boolean;
|
|
70
|
+
version: string;
|
|
71
|
+
rolledBackFrom: string;
|
|
72
|
+
message: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* List environments for the organization
|
|
76
|
+
* Note: Environments are organization-scoped, not project-scoped.
|
|
77
|
+
* The projectId parameter is kept for backward compatibility but not used for filtering.
|
|
78
|
+
*/
|
|
79
|
+
export declare function listEnvironments(client: RelesioAPIClient, _projectId?: string): Promise<{
|
|
80
|
+
environments: EnvironmentWithDeployment[];
|
|
81
|
+
count: number;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Deploy version to environment
|
|
85
|
+
*/
|
|
86
|
+
export declare function deployVersion(client: RelesioAPIClient, projectId: string, environmentId: string, input: CreateDeploymentInput): Promise<CreateDeploymentResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* Rollback to previous version
|
|
89
|
+
*/
|
|
90
|
+
export declare function rollback(client: RelesioAPIClient, projectId: string, environmentId: string): Promise<RollbackResponse>;
|
|
91
|
+
/**
|
|
92
|
+
* Get deployment history for environment
|
|
93
|
+
*/
|
|
94
|
+
export declare function getDeploymentHistory(client: RelesioAPIClient, projectId: string, environmentId: string, limit?: number): Promise<{
|
|
95
|
+
deployments: DeploymentHistoryItem[];
|
|
96
|
+
count: number;
|
|
97
|
+
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Get deployment status for all environments
|
|
100
|
+
*/
|
|
101
|
+
export declare function getDeploymentStatus(client: RelesioAPIClient, projectId: string): Promise<{
|
|
102
|
+
project: {
|
|
103
|
+
id: string;
|
|
104
|
+
name: string;
|
|
105
|
+
slug: string;
|
|
106
|
+
};
|
|
107
|
+
status: Array<{
|
|
108
|
+
environment: Environment;
|
|
109
|
+
currentDeployment: {
|
|
110
|
+
deploymentId: string;
|
|
111
|
+
versionId: string;
|
|
112
|
+
semanticVersion?: string | null;
|
|
113
|
+
version: string;
|
|
114
|
+
deployedAt: string;
|
|
115
|
+
deployedBy: string;
|
|
116
|
+
} | null;
|
|
117
|
+
}>;
|
|
118
|
+
}>;
|
|
119
|
+
/**
|
|
120
|
+
* Helper: Get environment by slug
|
|
121
|
+
*/
|
|
122
|
+
export declare function getEnvironmentBySlug(client: RelesioAPIClient, projectId: string, slug: string): Promise<EnvironmentWithDeployment | null>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List environments for the organization
|
|
3
|
+
* Note: Environments are organization-scoped, not project-scoped.
|
|
4
|
+
* The projectId parameter is kept for backward compatibility but not used for filtering.
|
|
5
|
+
*/
|
|
6
|
+
export async function listEnvironments(client, _projectId) {
|
|
7
|
+
const response = await client.get("/v1/environments", { raw: true, query: { limit: 100 } });
|
|
8
|
+
// Environments are organization-scoped, so no filtering needed
|
|
9
|
+
// The API already returns only environments for the authenticated organization
|
|
10
|
+
return {
|
|
11
|
+
environments: response.data,
|
|
12
|
+
count: response.meta?.count ?? response.data.length
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Deploy version to environment
|
|
17
|
+
*/
|
|
18
|
+
export async function deployVersion(client, projectId, environmentId, input) {
|
|
19
|
+
return client.post(`/v1/environments/${environmentId}/deployments`, { ...input, projectId });
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Rollback to previous version
|
|
23
|
+
*/
|
|
24
|
+
export async function rollback(client, projectId, environmentId) {
|
|
25
|
+
return client.post(`/v1/environments/${environmentId}/rollback`, { projectId });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get deployment history for environment
|
|
29
|
+
*/
|
|
30
|
+
export async function getDeploymentHistory(client, projectId, environmentId, limit = 50) {
|
|
31
|
+
const response = await client.get(`/v1/environments/${environmentId}/deployments`, {
|
|
32
|
+
query: { projectId, limit },
|
|
33
|
+
raw: true
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
deployments: response.data.map((d) => ({
|
|
37
|
+
...d,
|
|
38
|
+
deploymentId: d.deploymentId
|
|
39
|
+
})),
|
|
40
|
+
count: response.meta?.count ?? response.data.length
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get deployment status for all environments
|
|
45
|
+
*/
|
|
46
|
+
export async function getDeploymentStatus(client, projectId) {
|
|
47
|
+
return client.get(`/v1/projects/${projectId}/deployments/status`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Helper: Get environment by slug
|
|
51
|
+
*/
|
|
52
|
+
export async function getEnvironmentBySlug(client, projectId, slug) {
|
|
53
|
+
const { environments } = await listEnvironments(client, projectId);
|
|
54
|
+
return environments.find((env) => env.slug === slug) || null;
|
|
55
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RelesioAPIClient } from "./client.js";
|
|
2
|
+
import type { Organization, CreateOrganizationData, UpdateOrganizationData, UserOrganizationsResponse } from "./types.js";
|
|
3
|
+
export declare class OrganizationsAPI {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: RelesioAPIClient);
|
|
6
|
+
list(): Promise<Organization[]>;
|
|
7
|
+
create(data: CreateOrganizationData): Promise<Organization>;
|
|
8
|
+
get(orgId: string): Promise<Organization>;
|
|
9
|
+
update(orgId: string, data: UpdateOrganizationData): Promise<Organization>;
|
|
10
|
+
delete(orgId: string): Promise<void>;
|
|
11
|
+
switch(orgId: string): Promise<{
|
|
12
|
+
organizationId: string;
|
|
13
|
+
organizationName: string;
|
|
14
|
+
}>;
|
|
15
|
+
getUserOrgs(): Promise<UserOrganizationsResponse>;
|
|
16
|
+
/**
|
|
17
|
+
* Validate API token and get organization info
|
|
18
|
+
* Uses API key authentication (rls_...)
|
|
19
|
+
*
|
|
20
|
+
* @deprecated Use /v1/api-token/me endpoint for richer context (includes user info, all orgs)
|
|
21
|
+
*/
|
|
22
|
+
validateApiToken(): Promise<{
|
|
23
|
+
organizationId: string;
|
|
24
|
+
organizationName: string;
|
|
25
|
+
tokenId: string;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class OrganizationsAPI {
|
|
2
|
+
client;
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
async list() {
|
|
7
|
+
return this.client.get("/v1/organizations");
|
|
8
|
+
}
|
|
9
|
+
async create(data) {
|
|
10
|
+
return this.client.post("/v1/organizations", data);
|
|
11
|
+
}
|
|
12
|
+
async get(orgId) {
|
|
13
|
+
return this.client.get(`/v1/organizations/${orgId}`);
|
|
14
|
+
}
|
|
15
|
+
async update(orgId, data) {
|
|
16
|
+
return this.client.patch(`/v1/organizations/${orgId}`, data);
|
|
17
|
+
}
|
|
18
|
+
async delete(orgId) {
|
|
19
|
+
return this.client.delete(`/v1/organizations/${orgId}`);
|
|
20
|
+
}
|
|
21
|
+
async switch(orgId) {
|
|
22
|
+
return this.client.post("/v1/users/me/organization", { organizationId: orgId });
|
|
23
|
+
}
|
|
24
|
+
async getUserOrgs() {
|
|
25
|
+
return this.client.get("/v1/users/me/organizations");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validate API token and get organization info
|
|
29
|
+
* Uses API key authentication (rls_...)
|
|
30
|
+
*
|
|
31
|
+
* @deprecated Use /v1/api-token/me endpoint for richer context (includes user info, all orgs)
|
|
32
|
+
*/
|
|
33
|
+
async validateApiToken() {
|
|
34
|
+
// Note: client.get() already extracts the .data property from API responses
|
|
35
|
+
return this.client.get("/v1/api-token/validate");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RelesioAPIClient } from "./client.js";
|
|
2
|
+
export interface Project {
|
|
3
|
+
id: string;
|
|
4
|
+
organizationId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
updatedAt: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CreateProjectInput {
|
|
11
|
+
name: string;
|
|
12
|
+
slug: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ListProjectsResponse {
|
|
15
|
+
projects: Project[];
|
|
16
|
+
count: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* List all projects for the organization
|
|
20
|
+
*/
|
|
21
|
+
export declare function listProjects(client: RelesioAPIClient): Promise<ListProjectsResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* Get project by ID
|
|
24
|
+
*/
|
|
25
|
+
export declare function getProject(client: RelesioAPIClient, projectId: string): Promise<{
|
|
26
|
+
project: Project;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Create a new project
|
|
30
|
+
*/
|
|
31
|
+
export declare function createProject(client: RelesioAPIClient, input: CreateProjectInput): Promise<{
|
|
32
|
+
project: Project;
|
|
33
|
+
message: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Get project by slug (helper)
|
|
37
|
+
*/
|
|
38
|
+
export declare function getProjectBySlug(client: RelesioAPIClient, slug: string): Promise<Project | null>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List all projects for the organization
|
|
3
|
+
*/
|
|
4
|
+
export async function listProjects(client) {
|
|
5
|
+
const response = await client.get("/v1/projects", { raw: true });
|
|
6
|
+
return {
|
|
7
|
+
projects: response.data,
|
|
8
|
+
count: response.meta?.count ?? response.data.length
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get project by ID
|
|
13
|
+
*/
|
|
14
|
+
export async function getProject(client, projectId) {
|
|
15
|
+
const response = await client.get(`/v1/projects/${projectId}`, { raw: true });
|
|
16
|
+
return { project: response.data };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a new project
|
|
20
|
+
*/
|
|
21
|
+
export async function createProject(client, input) {
|
|
22
|
+
const response = await client.post("/v1/projects", input, { raw: true });
|
|
23
|
+
return {
|
|
24
|
+
project: response.data,
|
|
25
|
+
message: response.message ?? "Project created"
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get project by slug (helper)
|
|
30
|
+
*/
|
|
31
|
+
export async function getProjectBySlug(client, slug) {
|
|
32
|
+
const { projects } = await listProjects(client);
|
|
33
|
+
return projects.find((p) => p.slug === slug) || null;
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RelesioAPIClient } from "./client.js";
|
|
2
|
+
import type { Team, CreateTeamData, UpdateTeamData, TeamMember, AddTeamMemberData, UpdateTeamMemberData, PaginationQuery, APIResponse } from "./types.js";
|
|
3
|
+
export declare class TeamsAPI {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: RelesioAPIClient);
|
|
6
|
+
list(query?: PaginationQuery): Promise<APIResponse<Team[]>>;
|
|
7
|
+
create(data: CreateTeamData): Promise<Team>;
|
|
8
|
+
get(teamId: string): Promise<Team>;
|
|
9
|
+
update(teamId: string, data: UpdateTeamData): Promise<Team>;
|
|
10
|
+
delete(teamId: string): Promise<void>;
|
|
11
|
+
listMembers(teamId: string, query?: PaginationQuery): Promise<APIResponse<TeamMember[]>>;
|
|
12
|
+
addMember(teamId: string, data: AddTeamMemberData): Promise<TeamMember>;
|
|
13
|
+
updateMember(teamId: string, memberId: string, data: UpdateTeamMemberData): Promise<TeamMember>;
|
|
14
|
+
removeMember(teamId: string, memberId: string): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export class TeamsAPI {
|
|
2
|
+
client;
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
async list(query) {
|
|
7
|
+
const response = await this.client.get("/v1/teams", { query, raw: true });
|
|
8
|
+
return {
|
|
9
|
+
data: response.data,
|
|
10
|
+
message: response.message ?? "Teams retrieved",
|
|
11
|
+
pagination: response.meta?.pagination
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
async create(data) {
|
|
15
|
+
return this.client.post("/v1/teams", data);
|
|
16
|
+
}
|
|
17
|
+
async get(teamId) {
|
|
18
|
+
return this.client.get(`/v1/teams/${teamId}`);
|
|
19
|
+
}
|
|
20
|
+
async update(teamId, data) {
|
|
21
|
+
return this.client.patch(`/v1/teams/${teamId}`, data);
|
|
22
|
+
}
|
|
23
|
+
async delete(teamId) {
|
|
24
|
+
return this.client.delete(`/v1/teams/${teamId}`);
|
|
25
|
+
}
|
|
26
|
+
// Team Members
|
|
27
|
+
async listMembers(teamId, query) {
|
|
28
|
+
const response = await this.client.get(`/v1/teams/${teamId}/members`, { query, raw: true });
|
|
29
|
+
return {
|
|
30
|
+
data: response.data,
|
|
31
|
+
message: response.message ?? "Team members retrieved",
|
|
32
|
+
pagination: response.meta?.pagination
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async addMember(teamId, data) {
|
|
36
|
+
return this.client.post(`/v1/teams/${teamId}/members`, data);
|
|
37
|
+
}
|
|
38
|
+
async updateMember(teamId, memberId, data) {
|
|
39
|
+
return this.client.patch(`/v1/teams/${teamId}/members/${memberId}`, data);
|
|
40
|
+
}
|
|
41
|
+
async removeMember(teamId, memberId) {
|
|
42
|
+
return this.client.delete(`/v1/teams/${teamId}/members/${memberId}`);
|
|
43
|
+
}
|
|
44
|
+
}
|