@upfluxhq/cli 0.1.0-beta.1
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 +195 -0
- package/dist/client/apiClient.d.ts +1 -0
- package/dist/client/apiClient.js +43 -0
- package/dist/commands/generate-manifest.d.ts +12 -0
- package/dist/commands/generate-manifest.js +152 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.js +124 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.js +83 -0
- package/dist/commands/release.d.ts +3 -0
- package/dist/commands/release.js +554 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +90 -0
- package/dist/config/configStore.d.ts +73 -0
- package/dist/config/configStore.js +174 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -0
- package/dist/types/index.d.ts +85 -0
- package/dist/types/index.js +2 -0
- package/package.json +50 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single credential entry
|
|
3
|
+
*/
|
|
4
|
+
export interface Credential {
|
|
5
|
+
key: string;
|
|
6
|
+
appId: string;
|
|
7
|
+
platform?: 'ios' | 'android';
|
|
8
|
+
deploymentId: string;
|
|
9
|
+
deploymentName?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const configStore: {
|
|
12
|
+
/**
|
|
13
|
+
* Add or update a credential
|
|
14
|
+
* If same deploymentId exists, updates it; otherwise appends
|
|
15
|
+
*/
|
|
16
|
+
addCredential(cred: Credential): void;
|
|
17
|
+
/**
|
|
18
|
+
* Remove a credential by deployment ID
|
|
19
|
+
*/
|
|
20
|
+
removeCredential(deploymentId: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Remove all credentials
|
|
23
|
+
*/
|
|
24
|
+
removeAllCredentials(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get all credentials
|
|
27
|
+
*/
|
|
28
|
+
getCredentials(): Credential[];
|
|
29
|
+
/**
|
|
30
|
+
* Get the active credential
|
|
31
|
+
*/
|
|
32
|
+
getActiveCredential(): Credential | null;
|
|
33
|
+
/**
|
|
34
|
+
* Set active credential by index
|
|
35
|
+
*/
|
|
36
|
+
setActiveIndex(index: number): void;
|
|
37
|
+
/**
|
|
38
|
+
* Get credential by deployment ID
|
|
39
|
+
*/
|
|
40
|
+
getCredentialByDeployment(deploymentId: string): Credential | null;
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated Use addCredential instead
|
|
43
|
+
*/
|
|
44
|
+
saveAuth(key: string, appId?: string, deploymentId?: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* @deprecated Use addCredential instead
|
|
47
|
+
*/
|
|
48
|
+
saveAuthKey(key: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get the auth key (returns active credential's key)
|
|
51
|
+
*/
|
|
52
|
+
getAuthKey(): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Get the stored app ID (returns active credential's appId)
|
|
55
|
+
*/
|
|
56
|
+
getAppId(): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Get the stored deployment ID (returns active credential's deploymentId)
|
|
59
|
+
*/
|
|
60
|
+
getDeploymentId(): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Get full config (for release command compatibility)
|
|
63
|
+
*/
|
|
64
|
+
getConfig(): {
|
|
65
|
+
key: string;
|
|
66
|
+
appId?: string;
|
|
67
|
+
deploymentId?: string;
|
|
68
|
+
} | null;
|
|
69
|
+
/**
|
|
70
|
+
* Check if authenticated
|
|
71
|
+
*/
|
|
72
|
+
isAuthenticated(): boolean;
|
|
73
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configStore = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const CONFIG_FILE = path_1.default.join(process.cwd(), ".upflux");
|
|
10
|
+
/**
|
|
11
|
+
* Read the current config from file
|
|
12
|
+
*/
|
|
13
|
+
function readConfig() {
|
|
14
|
+
try {
|
|
15
|
+
const data = fs_1.default.readFileSync(CONFIG_FILE, "utf8");
|
|
16
|
+
const parsed = JSON.parse(data);
|
|
17
|
+
// Check if it's legacy format (has 'key' at root level)
|
|
18
|
+
if (parsed.key && !parsed.credentials) {
|
|
19
|
+
// Migrate legacy format to new format
|
|
20
|
+
const legacy = parsed;
|
|
21
|
+
return {
|
|
22
|
+
credentials: legacy.appId ? [{
|
|
23
|
+
key: legacy.key,
|
|
24
|
+
appId: legacy.appId,
|
|
25
|
+
deploymentId: legacy.deploymentId || "",
|
|
26
|
+
}] : [],
|
|
27
|
+
activeIndex: 0,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
catch (_a) {
|
|
33
|
+
return { credentials: [], activeIndex: 0 };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Write config to file
|
|
38
|
+
*/
|
|
39
|
+
function writeConfig(config) {
|
|
40
|
+
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
41
|
+
}
|
|
42
|
+
exports.configStore = {
|
|
43
|
+
/**
|
|
44
|
+
* Add or update a credential
|
|
45
|
+
* If same deploymentId exists, updates it; otherwise appends
|
|
46
|
+
*/
|
|
47
|
+
addCredential(cred) {
|
|
48
|
+
const config = readConfig();
|
|
49
|
+
// Check if credential for this deployment already exists
|
|
50
|
+
const existingIndex = config.credentials.findIndex(c => c.deploymentId === cred.deploymentId);
|
|
51
|
+
if (existingIndex >= 0) {
|
|
52
|
+
// Update existing
|
|
53
|
+
config.credentials[existingIndex] = cred;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Add new
|
|
57
|
+
config.credentials.push(cred);
|
|
58
|
+
}
|
|
59
|
+
// If this is the only credential, set it as active
|
|
60
|
+
if (config.credentials.length === 1) {
|
|
61
|
+
config.activeIndex = 0;
|
|
62
|
+
}
|
|
63
|
+
writeConfig(config);
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Remove a credential by deployment ID
|
|
67
|
+
*/
|
|
68
|
+
removeCredential(deploymentId) {
|
|
69
|
+
const config = readConfig();
|
|
70
|
+
const index = config.credentials.findIndex(c => c.deploymentId === deploymentId);
|
|
71
|
+
if (index < 0)
|
|
72
|
+
return false;
|
|
73
|
+
config.credentials.splice(index, 1);
|
|
74
|
+
// Adjust activeIndex if needed
|
|
75
|
+
if (config.activeIndex >= config.credentials.length) {
|
|
76
|
+
config.activeIndex = Math.max(0, config.credentials.length - 1);
|
|
77
|
+
}
|
|
78
|
+
writeConfig(config);
|
|
79
|
+
return true;
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* Remove all credentials
|
|
83
|
+
*/
|
|
84
|
+
removeAllCredentials() {
|
|
85
|
+
writeConfig({ credentials: [], activeIndex: 0 });
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Get all credentials
|
|
89
|
+
*/
|
|
90
|
+
getCredentials() {
|
|
91
|
+
return readConfig().credentials;
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Get the active credential
|
|
95
|
+
*/
|
|
96
|
+
getActiveCredential() {
|
|
97
|
+
const config = readConfig();
|
|
98
|
+
return config.credentials[config.activeIndex] || null;
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* Set active credential by index
|
|
102
|
+
*/
|
|
103
|
+
setActiveIndex(index) {
|
|
104
|
+
const config = readConfig();
|
|
105
|
+
if (index >= 0 && index < config.credentials.length) {
|
|
106
|
+
config.activeIndex = index;
|
|
107
|
+
writeConfig(config);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
/**
|
|
111
|
+
* Get credential by deployment ID
|
|
112
|
+
*/
|
|
113
|
+
getCredentialByDeployment(deploymentId) {
|
|
114
|
+
const config = readConfig();
|
|
115
|
+
return config.credentials.find(c => c.deploymentId === deploymentId) || null;
|
|
116
|
+
},
|
|
117
|
+
// ============================================
|
|
118
|
+
// Legacy methods for backward compatibility
|
|
119
|
+
// ============================================
|
|
120
|
+
/**
|
|
121
|
+
* @deprecated Use addCredential instead
|
|
122
|
+
*/
|
|
123
|
+
saveAuth(key, appId, deploymentId) {
|
|
124
|
+
if (appId && deploymentId) {
|
|
125
|
+
this.addCredential({ key, appId, deploymentId });
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
/**
|
|
129
|
+
* @deprecated Use addCredential instead
|
|
130
|
+
*/
|
|
131
|
+
saveAuthKey(key) {
|
|
132
|
+
// Can't save without app/deployment info - do nothing
|
|
133
|
+
},
|
|
134
|
+
/**
|
|
135
|
+
* Get the auth key (returns active credential's key)
|
|
136
|
+
*/
|
|
137
|
+
getAuthKey() {
|
|
138
|
+
var _a;
|
|
139
|
+
return ((_a = this.getActiveCredential()) === null || _a === void 0 ? void 0 : _a.key) || null;
|
|
140
|
+
},
|
|
141
|
+
/**
|
|
142
|
+
* Get the stored app ID (returns active credential's appId)
|
|
143
|
+
*/
|
|
144
|
+
getAppId() {
|
|
145
|
+
var _a;
|
|
146
|
+
return ((_a = this.getActiveCredential()) === null || _a === void 0 ? void 0 : _a.appId) || null;
|
|
147
|
+
},
|
|
148
|
+
/**
|
|
149
|
+
* Get the stored deployment ID (returns active credential's deploymentId)
|
|
150
|
+
*/
|
|
151
|
+
getDeploymentId() {
|
|
152
|
+
var _a;
|
|
153
|
+
return ((_a = this.getActiveCredential()) === null || _a === void 0 ? void 0 : _a.deploymentId) || null;
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Get full config (for release command compatibility)
|
|
157
|
+
*/
|
|
158
|
+
getConfig() {
|
|
159
|
+
const active = this.getActiveCredential();
|
|
160
|
+
if (!active)
|
|
161
|
+
return null;
|
|
162
|
+
return {
|
|
163
|
+
key: active.key,
|
|
164
|
+
appId: active.appId,
|
|
165
|
+
deploymentId: active.deploymentId,
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
/**
|
|
169
|
+
* Check if authenticated
|
|
170
|
+
*/
|
|
171
|
+
isAuthenticated() {
|
|
172
|
+
return this.getCredentials().length > 0;
|
|
173
|
+
},
|
|
174
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const login_1 = __importDefault(require("./commands/login"));
|
|
9
|
+
const logout_1 = __importDefault(require("./commands/logout"));
|
|
10
|
+
const release_1 = __importDefault(require("./commands/release"));
|
|
11
|
+
const status_1 = __importDefault(require("./commands/status"));
|
|
12
|
+
const generate_manifest_1 = __importDefault(require("./commands/generate-manifest"));
|
|
13
|
+
const program = new commander_1.Command();
|
|
14
|
+
program
|
|
15
|
+
.name("upflux")
|
|
16
|
+
.description("Upflux CLI for OTA updates")
|
|
17
|
+
.version("0.0.1");
|
|
18
|
+
program.addCommand(login_1.default);
|
|
19
|
+
program.addCommand(logout_1.default);
|
|
20
|
+
program.addCommand(release_1.default);
|
|
21
|
+
program.addCommand(status_1.default);
|
|
22
|
+
program.addCommand(generate_manifest_1.default);
|
|
23
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export interface ReleaseOptions {
|
|
2
|
+
deployment: string;
|
|
3
|
+
mandatory?: boolean;
|
|
4
|
+
rollout?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Release Manifest structure for OTA updates.
|
|
8
|
+
* Generated by the CLI and consumed by client SDKs.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReleaseManifest {
|
|
11
|
+
releaseLabel: string;
|
|
12
|
+
bundleUrl: string;
|
|
13
|
+
assets: string[];
|
|
14
|
+
mandatory?: boolean;
|
|
15
|
+
binaryVersionRange?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* API Response for a single release
|
|
19
|
+
*/
|
|
20
|
+
export interface ReleaseResponse {
|
|
21
|
+
id: string;
|
|
22
|
+
releaseLabel: string;
|
|
23
|
+
bundleUrl: string;
|
|
24
|
+
assets: string[];
|
|
25
|
+
rolloutPercentage: number;
|
|
26
|
+
mandatory: boolean;
|
|
27
|
+
binaryVersionRange?: string;
|
|
28
|
+
appId: string;
|
|
29
|
+
deploymentId: string;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt?: string;
|
|
32
|
+
status?: 'draft' | 'scheduled' | 'active' | 'expired';
|
|
33
|
+
scheduledAt?: string;
|
|
34
|
+
expiresAt?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* API Response for listing releases
|
|
38
|
+
*/
|
|
39
|
+
export interface ListReleasesResponse {
|
|
40
|
+
releases: ReleaseResponse[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Payload for creating a new release
|
|
44
|
+
*/
|
|
45
|
+
export interface CreateReleasePayload {
|
|
46
|
+
releaseLabel: string;
|
|
47
|
+
appId: string;
|
|
48
|
+
deploymentId: string;
|
|
49
|
+
mandatory?: boolean;
|
|
50
|
+
rolloutPercentage?: number;
|
|
51
|
+
binaryVersionRange?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* API Response for a deployment
|
|
55
|
+
*/
|
|
56
|
+
export interface DeploymentResponse {
|
|
57
|
+
id: string;
|
|
58
|
+
name: string;
|
|
59
|
+
appId: string;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
updatedAt?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* API Response for listing deployments
|
|
65
|
+
*/
|
|
66
|
+
export interface ListDeploymentsResponse {
|
|
67
|
+
deployments: DeploymentResponse[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* API Response for an app
|
|
71
|
+
*/
|
|
72
|
+
export interface AppResponse {
|
|
73
|
+
id: string;
|
|
74
|
+
appId: string;
|
|
75
|
+
name: string;
|
|
76
|
+
platform: string;
|
|
77
|
+
createdAt: string;
|
|
78
|
+
updatedAt?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* API Response for listing apps
|
|
82
|
+
*/
|
|
83
|
+
export interface ListAppsResponse {
|
|
84
|
+
apps: AppResponse[];
|
|
85
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@upfluxhq/cli",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "Upflux CLI for managing OTA updates",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"upflux": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p ."
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"upflux",
|
|
15
|
+
"cli",
|
|
16
|
+
"ota",
|
|
17
|
+
"deployment"
|
|
18
|
+
],
|
|
19
|
+
"author": "Upflux Team <support@upflux.in>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"homepage": "https://upflux.in",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"email": "support@upflux.in"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18.0.0"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"archiver": "^7.0.0",
|
|
37
|
+
"axios": "^1.6.2",
|
|
38
|
+
"chalk": "4",
|
|
39
|
+
"commander": "^11.1.0",
|
|
40
|
+
"form-data": "^4.0.5",
|
|
41
|
+
"inquirer": "^9"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/archiver": "^7.0.0",
|
|
45
|
+
"@types/form-data": "^2.5.2",
|
|
46
|
+
"@types/inquirer": "^9.0.9",
|
|
47
|
+
"@types/node": "^20.10.0",
|
|
48
|
+
"typescript": "^5.3.0"
|
|
49
|
+
}
|
|
50
|
+
}
|