@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.
Files changed (75) hide show
  1. package/README.md +224 -0
  2. package/bin/relesio.js +4 -0
  3. package/dist/commands/auth/index.d.ts +2 -0
  4. package/dist/commands/auth/index.js +9 -0
  5. package/dist/commands/auth/login.d.ts +2 -0
  6. package/dist/commands/auth/login.js +82 -0
  7. package/dist/commands/auth/logout.d.ts +2 -0
  8. package/dist/commands/auth/logout.js +25 -0
  9. package/dist/commands/auth/status.d.ts +2 -0
  10. package/dist/commands/auth/status.js +35 -0
  11. package/dist/commands/deploy.d.ts +2 -0
  12. package/dist/commands/deploy.js +293 -0
  13. package/dist/commands/organizations/index.d.ts +2 -0
  14. package/dist/commands/organizations/index.js +8 -0
  15. package/dist/commands/organizations/list.d.ts +2 -0
  16. package/dist/commands/organizations/list.js +54 -0
  17. package/dist/commands/organizations/set.d.ts +2 -0
  18. package/dist/commands/organizations/set.js +34 -0
  19. package/dist/commands/projects/index.d.ts +2 -0
  20. package/dist/commands/projects/index.js +6 -0
  21. package/dist/commands/projects/list.d.ts +2 -0
  22. package/dist/commands/projects/list.js +49 -0
  23. package/dist/commands/rollback.d.ts +2 -0
  24. package/dist/commands/rollback.js +119 -0
  25. package/dist/commands/status.d.ts +2 -0
  26. package/dist/commands/status.js +59 -0
  27. package/dist/commands/team/get.d.ts +2 -0
  28. package/dist/commands/team/get.js +34 -0
  29. package/dist/commands/team/index.d.ts +2 -0
  30. package/dist/commands/team/index.js +7 -0
  31. package/dist/commands/team/list.d.ts +2 -0
  32. package/dist/commands/team/list.js +46 -0
  33. package/dist/commands/upload.d.ts +2 -0
  34. package/dist/commands/upload.js +365 -0
  35. package/dist/commands/versions/index.d.ts +2 -0
  36. package/dist/commands/versions/index.js +6 -0
  37. package/dist/commands/versions/list.d.ts +2 -0
  38. package/dist/commands/versions/list.js +51 -0
  39. package/dist/commands/whoami.d.ts +2 -0
  40. package/dist/commands/whoami.js +52 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.js +90 -0
  43. package/dist/lib/api/client.d.ts +32 -0
  44. package/dist/lib/api/client.js +187 -0
  45. package/dist/lib/api/deployments.d.ts +122 -0
  46. package/dist/lib/api/deployments.js +55 -0
  47. package/dist/lib/api/organizations.d.ts +27 -0
  48. package/dist/lib/api/organizations.js +37 -0
  49. package/dist/lib/api/projects.d.ts +38 -0
  50. package/dist/lib/api/projects.js +34 -0
  51. package/dist/lib/api/teams.d.ts +15 -0
  52. package/dist/lib/api/teams.js +44 -0
  53. package/dist/lib/api/types.d.ts +89 -0
  54. package/dist/lib/api/types.js +2 -0
  55. package/dist/lib/api/versions.d.ts +140 -0
  56. package/dist/lib/api/versions.js +53 -0
  57. package/dist/lib/config/manager.d.ts +35 -0
  58. package/dist/lib/config/manager.js +78 -0
  59. package/dist/lib/config/types.d.ts +15 -0
  60. package/dist/lib/config/types.js +15 -0
  61. package/dist/lib/errors/handler.d.ts +1 -0
  62. package/dist/lib/errors/handler.js +75 -0
  63. package/dist/lib/errors/types.d.ts +19 -0
  64. package/dist/lib/errors/types.js +34 -0
  65. package/dist/lib/files/scanner.d.ts +23 -0
  66. package/dist/lib/files/scanner.js +81 -0
  67. package/dist/lib/git/metadata.d.ts +31 -0
  68. package/dist/lib/git/metadata.js +90 -0
  69. package/dist/lib/output/colors.d.ts +14 -0
  70. package/dist/lib/output/colors.js +23 -0
  71. package/dist/lib/output/formatter.d.ts +2 -0
  72. package/dist/lib/output/formatter.js +7 -0
  73. package/dist/lib/output/table.d.ts +7 -0
  74. package/dist/lib/output/table.js +64 -0
  75. 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
+ }