@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
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git metadata collected from the repository
|
|
3
|
+
*/
|
|
4
|
+
export interface GitMetadata {
|
|
5
|
+
sha?: string;
|
|
6
|
+
branch?: string;
|
|
7
|
+
commitMessage?: string;
|
|
8
|
+
author?: string;
|
|
9
|
+
tag?: string;
|
|
10
|
+
isDirty: boolean;
|
|
11
|
+
remoteUrl?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Collect git metadata from the current repository
|
|
15
|
+
* Automatically called during upload to track version provenance
|
|
16
|
+
*
|
|
17
|
+
* @returns Git metadata or empty object if not in a git repository
|
|
18
|
+
*/
|
|
19
|
+
export declare function collectGitMetadata(): Promise<GitMetadata>;
|
|
20
|
+
/**
|
|
21
|
+
* Validate git state before deployment
|
|
22
|
+
*
|
|
23
|
+
* @param metadata - Git metadata
|
|
24
|
+
* @param requireClean - Whether to require clean working directory
|
|
25
|
+
* @throws Error if validation fails
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateGitState(metadata: GitMetadata, requireClean?: boolean): void;
|
|
28
|
+
/**
|
|
29
|
+
* Format git metadata for display
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatGitMetadata(metadata: GitMetadata): string;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Collect git metadata from the current repository
|
|
4
|
+
* Automatically called during upload to track version provenance
|
|
5
|
+
*
|
|
6
|
+
* @returns Git metadata or empty object if not in a git repository
|
|
7
|
+
*/
|
|
8
|
+
export async function collectGitMetadata() {
|
|
9
|
+
try {
|
|
10
|
+
// Check if in git repository
|
|
11
|
+
execSync("git rev-parse --git-dir", { stdio: "pipe" });
|
|
12
|
+
const sha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
|
|
13
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
14
|
+
encoding: "utf8"
|
|
15
|
+
}).trim();
|
|
16
|
+
const commitMessage = execSync("git log -1 --pretty=%B", {
|
|
17
|
+
encoding: "utf8"
|
|
18
|
+
}).trim();
|
|
19
|
+
const author = execSync('git log -1 --pretty=format:"%an <%ae>"', {
|
|
20
|
+
encoding: "utf8"
|
|
21
|
+
}).trim();
|
|
22
|
+
// Check for tag on current commit
|
|
23
|
+
let tag;
|
|
24
|
+
try {
|
|
25
|
+
tag = execSync("git describe --exact-match --tags HEAD", {
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
stdio: "pipe"
|
|
28
|
+
}).trim();
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// No tag on current commit
|
|
32
|
+
}
|
|
33
|
+
// Check if working directory is dirty
|
|
34
|
+
const status = execSync("git status --porcelain", { encoding: "utf8" });
|
|
35
|
+
const isDirty = status.trim().length > 0;
|
|
36
|
+
let remoteUrl;
|
|
37
|
+
try {
|
|
38
|
+
remoteUrl = execSync("git config --get remote.origin.url", {
|
|
39
|
+
encoding: "utf8"
|
|
40
|
+
}).trim();
|
|
41
|
+
// Sanitize credentials from URL
|
|
42
|
+
remoteUrl = remoteUrl.replace(/\/\/[^@]+@/, "//");
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// No remote configured
|
|
46
|
+
}
|
|
47
|
+
return { sha, branch, commitMessage, author, tag, isDirty, remoteUrl };
|
|
48
|
+
}
|
|
49
|
+
catch (_error) {
|
|
50
|
+
// Not a git repository or git not available
|
|
51
|
+
return { isDirty: false };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate git state before deployment
|
|
56
|
+
*
|
|
57
|
+
* @param metadata - Git metadata
|
|
58
|
+
* @param requireClean - Whether to require clean working directory
|
|
59
|
+
* @throws Error if validation fails
|
|
60
|
+
*/
|
|
61
|
+
export function validateGitState(metadata, requireClean = false) {
|
|
62
|
+
if (requireClean && metadata.isDirty) {
|
|
63
|
+
throw new Error("Working directory has uncommitted changes. Commit or stash changes before deploying.");
|
|
64
|
+
}
|
|
65
|
+
if (!metadata.sha) {
|
|
66
|
+
console.warn("⚠️ Not in a git repository. Version tracking will be limited.");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Format git metadata for display
|
|
71
|
+
*/
|
|
72
|
+
export function formatGitMetadata(metadata) {
|
|
73
|
+
const lines = [];
|
|
74
|
+
if (metadata.sha) {
|
|
75
|
+
lines.push(` Commit: ${metadata.sha.substring(0, 7)}`);
|
|
76
|
+
}
|
|
77
|
+
if (metadata.branch) {
|
|
78
|
+
lines.push(` Branch: ${metadata.branch}`);
|
|
79
|
+
}
|
|
80
|
+
if (metadata.tag) {
|
|
81
|
+
lines.push(` Tag: ${metadata.tag}`);
|
|
82
|
+
}
|
|
83
|
+
if (metadata.author) {
|
|
84
|
+
lines.push(` Author: ${metadata.author}`);
|
|
85
|
+
}
|
|
86
|
+
if (metadata.isDirty) {
|
|
87
|
+
lines.push(` Status: ⚠️ Uncommitted changes`);
|
|
88
|
+
}
|
|
89
|
+
return lines.join("\n");
|
|
90
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const colors: {
|
|
2
|
+
success: import("chalk").ChalkInstance;
|
|
3
|
+
error: import("chalk").ChalkInstance;
|
|
4
|
+
warning: import("chalk").ChalkInstance;
|
|
5
|
+
info: import("chalk").ChalkInstance;
|
|
6
|
+
dim: import("chalk").ChalkInstance;
|
|
7
|
+
bold: import("chalk").ChalkInstance;
|
|
8
|
+
highlight: import("chalk").ChalkInstance;
|
|
9
|
+
primary: import("chalk").ChalkInstance;
|
|
10
|
+
};
|
|
11
|
+
export declare function formatSuccess(message: string): string;
|
|
12
|
+
export declare function formatError(message: string): string;
|
|
13
|
+
export declare function formatWarning(message: string): string;
|
|
14
|
+
export declare function formatInfo(message: string): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
export const colors = {
|
|
3
|
+
success: chalk.green,
|
|
4
|
+
error: chalk.red,
|
|
5
|
+
warning: chalk.yellow,
|
|
6
|
+
info: chalk.blue,
|
|
7
|
+
dim: chalk.dim,
|
|
8
|
+
bold: chalk.bold,
|
|
9
|
+
highlight: chalk.cyan,
|
|
10
|
+
primary: chalk.magenta
|
|
11
|
+
};
|
|
12
|
+
export function formatSuccess(message) {
|
|
13
|
+
return colors.success(`✓ ${message}`);
|
|
14
|
+
}
|
|
15
|
+
export function formatError(message) {
|
|
16
|
+
return colors.error(`✗ ${message}`);
|
|
17
|
+
}
|
|
18
|
+
export function formatWarning(message) {
|
|
19
|
+
return colors.warning(`⚠ ${message}`);
|
|
20
|
+
}
|
|
21
|
+
export function formatInfo(message) {
|
|
22
|
+
return colors.info(`ℹ ${message}`);
|
|
23
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import Table from "cli-table3";
|
|
2
|
+
import type { Team, Organization } from "../api/types.js";
|
|
3
|
+
export declare function createTable(head: string[], options?: Record<string, unknown>): Table.Table;
|
|
4
|
+
export declare function renderOrganizationsTable(orgs: Organization[]): void;
|
|
5
|
+
export declare function renderTeamsTable(teams: Team[]): void;
|
|
6
|
+
export declare function renderTeamDetails(team: Team): void;
|
|
7
|
+
export declare function formatTable(headers: string[], rows: string[][]): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import Table from "cli-table3";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
export function createTable(head, options) {
|
|
4
|
+
return new Table({
|
|
5
|
+
head: head.map((h) => chalk.cyan(h)),
|
|
6
|
+
style: {
|
|
7
|
+
head: [],
|
|
8
|
+
border: ["dim"]
|
|
9
|
+
},
|
|
10
|
+
...options
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export function renderOrganizationsTable(orgs) {
|
|
14
|
+
if (orgs.length === 0) {
|
|
15
|
+
console.log(chalk.dim("No organizations found"));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const table = createTable(["ID", "Name", "Slug", "Members"]);
|
|
19
|
+
for (const org of orgs) {
|
|
20
|
+
table.push([
|
|
21
|
+
chalk.dim(org.id),
|
|
22
|
+
chalk.bold(org.name),
|
|
23
|
+
org.slug || chalk.dim("(none)"),
|
|
24
|
+
org.membersCount?.toString() || chalk.dim("0")
|
|
25
|
+
]);
|
|
26
|
+
}
|
|
27
|
+
console.log(table.toString());
|
|
28
|
+
console.log(chalk.dim(`\nTotal: ${orgs.length} organization${orgs.length !== 1 ? "s" : ""}`));
|
|
29
|
+
}
|
|
30
|
+
export function renderTeamsTable(teams) {
|
|
31
|
+
if (teams.length === 0) {
|
|
32
|
+
console.log(chalk.dim("No teams found"));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const table = createTable(["ID", "Name", "Description", "Members"]);
|
|
36
|
+
for (const team of teams) {
|
|
37
|
+
table.push([
|
|
38
|
+
chalk.dim(`${team.id.substring(0, 8)}...`),
|
|
39
|
+
chalk.bold(team.name),
|
|
40
|
+
team.description || chalk.dim("(no description)"),
|
|
41
|
+
team.memberCount?.toString() || chalk.dim("0")
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
console.log(table.toString());
|
|
45
|
+
console.log(chalk.dim(`\nTotal: ${teams.length} team${teams.length !== 1 ? "s" : ""}`));
|
|
46
|
+
}
|
|
47
|
+
export function renderTeamDetails(team) {
|
|
48
|
+
console.log(chalk.bold("\nTeam Details"));
|
|
49
|
+
console.log(chalk.dim("─".repeat(50)));
|
|
50
|
+
console.log(`${chalk.cyan("ID:")} ${chalk.dim(team.id)}`);
|
|
51
|
+
console.log(`${chalk.cyan("Name:")} ${chalk.bold(team.name)}`);
|
|
52
|
+
console.log(`${chalk.cyan("Description:")} ${team.description || chalk.dim("(no description)")}`);
|
|
53
|
+
console.log(`${chalk.cyan("Members:")} ${team.memberCount || 0}`);
|
|
54
|
+
console.log(`${chalk.cyan("Organization:")} ${chalk.dim(team.organizationId)}`);
|
|
55
|
+
console.log(`${chalk.cyan("Created:")} ${chalk.dim(new Date(team.createdAt).toLocaleString())}`);
|
|
56
|
+
console.log(`${chalk.cyan("Updated:")} ${chalk.dim(new Date(team.updatedAt).toLocaleString())}`);
|
|
57
|
+
}
|
|
58
|
+
export function formatTable(headers, rows) {
|
|
59
|
+
const table = createTable(headers);
|
|
60
|
+
for (const row of rows) {
|
|
61
|
+
table.push(row);
|
|
62
|
+
}
|
|
63
|
+
return table.toString();
|
|
64
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@relesio/cli",
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "CLI tool for Relesio - Modern Micro-Frontend Hosting",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"relesio": "./bin/relesio.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"bin"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "bun src/index.ts",
|
|
16
|
+
"build": "tsc -p tsconfig.build.json",
|
|
17
|
+
"type-check": "tsc --noEmit",
|
|
18
|
+
"lint": "biome lint --write .",
|
|
19
|
+
"format": "biome format --write .",
|
|
20
|
+
"format:check": "biome format .",
|
|
21
|
+
"test": "echo 'No tests yet'",
|
|
22
|
+
"clean": "rm -rf dist"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"chalk": "^5.3.0",
|
|
26
|
+
"cli-table3": "^0.6.5",
|
|
27
|
+
"commander": "^12.1.0",
|
|
28
|
+
"conf": "^13.0.1",
|
|
29
|
+
"inquirer": "^10.2.2",
|
|
30
|
+
"mime-types": "^2.1.35",
|
|
31
|
+
"ora": "^8.1.2",
|
|
32
|
+
"undici": "^6.0.0",
|
|
33
|
+
"zod": "^3.23.8"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@biomejs/biome": "2.3.10",
|
|
37
|
+
"@types/inquirer": "^9.0.7",
|
|
38
|
+
"@types/mime-types": "^2.1.4",
|
|
39
|
+
"@types/node": "^22.10.6",
|
|
40
|
+
"typescript": "^5.7.3"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18.0.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/relesio/relesio.git",
|
|
51
|
+
"directory": "api/apps/cli"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://relesio.io",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/relesio/relesio/issues"
|
|
56
|
+
},
|
|
57
|
+
"license": "MIT"
|
|
58
|
+
}
|