@upfluxhq/cli 1.1.0 → 1.3.0

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.
@@ -0,0 +1,196 @@
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
+ const commander_1 = require("commander");
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const UPFLUX_JSON_FILE = path_1.default.join(process.cwd(), "upflux.json");
12
+ const APP_JSON_FILE = path_1.default.join(process.cwd(), "app.json");
13
+ const DEFAULT_SERVER_URL = "https://api.upflux.in";
14
+ /**
15
+ * Build the upflux.json content from collected answers
16
+ */
17
+ function buildUpfluxJson(appId, serverUrl, runtimeVersion, profiles) {
18
+ const deployments = {};
19
+ for (const profile of profiles) {
20
+ const entry = {
21
+ clientKey: profile.clientKey,
22
+ };
23
+ if (profile.extendsProfile) {
24
+ entry.extends = profile.extendsProfile;
25
+ }
26
+ // Set sensible defaults per profile name
27
+ if (profile.name === "development") {
28
+ entry.checkOnLaunch = "always";
29
+ entry.installMode = "on_next_restart";
30
+ }
31
+ else if (profile.name === "production") {
32
+ entry.checkOnLaunch = "always";
33
+ entry.installMode = "immediate";
34
+ }
35
+ deployments[profile.name] = entry;
36
+ }
37
+ return {
38
+ version: 1,
39
+ app: Object.assign({ id: appId, buildNumber: 0, runtimeVersion }, (serverUrl !== DEFAULT_SERVER_URL ? { serverUrl } : {})),
40
+ deployments,
41
+ };
42
+ }
43
+ const init = new commander_1.Command("init")
44
+ .description("Scaffold upflux.json in your project root")
45
+ .option("--force", "Overwrite existing upflux.json")
46
+ .action(async (opts) => {
47
+ var _a, _b;
48
+ console.log(chalk_1.default.bold("\nšŸš€ Upflux Project Setup\n"));
49
+ // Detect Expo project
50
+ let isExpo = false;
51
+ let expoAppJson = null;
52
+ if (fs_1.default.existsSync(APP_JSON_FILE)) {
53
+ try {
54
+ const parsed = JSON.parse(fs_1.default.readFileSync(APP_JSON_FILE, "utf-8"));
55
+ if (parsed && parsed.expo) {
56
+ isExpo = true;
57
+ expoAppJson = parsed;
58
+ }
59
+ }
60
+ catch (_c) {
61
+ // Ignore parse errors
62
+ }
63
+ }
64
+ // Check if upflux.json already exists
65
+ if (fs_1.default.existsSync(UPFLUX_JSON_FILE) && !opts.force) {
66
+ console.log(chalk_1.default.yellow("āš ļø upflux.json already exists."));
67
+ const { overwrite } = await inquirer_1.default.prompt([
68
+ {
69
+ type: "confirm",
70
+ name: "overwrite",
71
+ message: "Overwrite it?",
72
+ default: false,
73
+ },
74
+ ]);
75
+ if (!overwrite) {
76
+ console.log(chalk_1.default.gray("Aborted."));
77
+ process.exit(0);
78
+ }
79
+ }
80
+ // Step 1: App ID
81
+ const { appId } = await inquirer_1.default.prompt([
82
+ {
83
+ type: "input",
84
+ name: "appId",
85
+ message: "App ID:",
86
+ validate: (val) => val.trim() ? true : "App ID is required",
87
+ },
88
+ ]);
89
+ // Step 2: Server URL
90
+ const { serverUrl } = await inquirer_1.default.prompt([
91
+ {
92
+ type: "input",
93
+ name: "serverUrl",
94
+ message: `Server URL (press Enter for ${DEFAULT_SERVER_URL}):`,
95
+ default: DEFAULT_SERVER_URL,
96
+ },
97
+ ]);
98
+ // Step 3: Runtime version (semver, used to form auto release labels)
99
+ const defaultRuntimeVersion = (isExpo && ((_a = expoAppJson === null || expoAppJson === void 0 ? void 0 : expoAppJson.expo) === null || _a === void 0 ? void 0 : _a.version))
100
+ ? expoAppJson.expo.version
101
+ : "1.0.0";
102
+ const { runtimeVersion } = await inquirer_1.default.prompt([
103
+ {
104
+ type: "input",
105
+ name: "runtimeVersion",
106
+ message: "Runtime version (e.g. 1.0.0 — update when shipping a new binary):",
107
+ default: defaultRuntimeVersion,
108
+ validate: (val) => {
109
+ if (!val.trim())
110
+ return "Runtime version is required";
111
+ if (!/^\d+\.\d+\.\d+/.test(val.trim()))
112
+ return "Use semver format, e.g. 1.0.0";
113
+ return true;
114
+ },
115
+ },
116
+ ]);
117
+ const { selectedProfiles } = await inquirer_1.default.prompt([
118
+ {
119
+ type: "checkbox",
120
+ name: "selectedProfiles",
121
+ message: "Deployment profiles to create:",
122
+ choices: [
123
+ { name: "production", checked: true },
124
+ { name: "staging", checked: true },
125
+ { name: "development", checked: true },
126
+ ],
127
+ validate: (selected) => selected.length > 0 ? true : "Select at least one profile",
128
+ },
129
+ ]);
130
+ // Step 4: Client keys per profile
131
+ const profiles = [];
132
+ for (const profileName of selectedProfiles) {
133
+ const { clientKey } = await inquirer_1.default.prompt([
134
+ {
135
+ type: "input",
136
+ name: "clientKey",
137
+ message: `Client key for "${chalk_1.default.cyan(profileName)}" ${chalk_1.default.gray("(upx_cli_xxxxx)")}:`,
138
+ validate: (val) => {
139
+ if (!val.trim())
140
+ return "Client key is required";
141
+ if (val.trim().length < 10)
142
+ return "Client key looks too short";
143
+ return true;
144
+ },
145
+ },
146
+ ]);
147
+ profiles.push({ name: profileName, clientKey: clientKey.trim() });
148
+ }
149
+ // Build and write upflux.json
150
+ const content = buildUpfluxJson(appId.trim(), serverUrl.trim(), runtimeVersion.trim(), profiles);
151
+ fs_1.default.writeFileSync(UPFLUX_JSON_FILE, JSON.stringify(content, null, 2));
152
+ console.log(chalk_1.default.green("\nāœ“ Created upflux.json\n"));
153
+ // Show what was created
154
+ console.log(chalk_1.default.gray("Preview:"));
155
+ console.log(chalk_1.default.gray(JSON.stringify(content, null, 2)));
156
+ if (isExpo && expoAppJson) {
157
+ const primaryProfile = profiles.find(p => p.name === "production") || profiles[0];
158
+ if (primaryProfile) {
159
+ const { updateAppJson } = await inquirer_1.default.prompt([
160
+ {
161
+ type: "confirm",
162
+ name: "updateAppJson",
163
+ message: `Configure app.json with Expo Updates URL and client key for "${primaryProfile.name}"?`,
164
+ default: true,
165
+ },
166
+ ]);
167
+ if (updateAppJson) {
168
+ expoAppJson.expo = expoAppJson.expo || {};
169
+ expoAppJson.expo.runtimeVersion = runtimeVersion.trim();
170
+ expoAppJson.expo.updates = Object.assign(Object.assign({}, (expoAppJson.expo.updates || {})), { url: `${serverUrl.trim()}/api/updates/check`, requestHeaders: Object.assign(Object.assign({}, (((_b = expoAppJson.expo.updates) === null || _b === void 0 ? void 0 : _b.requestHeaders) || {})), { "x-client-key": primaryProfile.clientKey.trim() }) });
171
+ fs_1.default.writeFileSync(APP_JSON_FILE, JSON.stringify(expoAppJson, null, 2));
172
+ console.log(chalk_1.default.green("āœ“ Updated app.json with Expo Updates config\n"));
173
+ }
174
+ }
175
+ console.log(chalk_1.default.bold("\nšŸ“± Expo Usage:\n"));
176
+ console.log(chalk_1.default.white(` 1. Install expo-updates:\n` +
177
+ ` npx expo install expo-updates\n\n` +
178
+ ` 2. Publish a release:\n` +
179
+ ` upflux release\n`));
180
+ }
181
+ else {
182
+ // Usage hint
183
+ console.log(chalk_1.default.bold("\nšŸ“¦ SDK Usage:\n"));
184
+ console.log(chalk_1.default.white(` import { Upflux } from '@upfluxhq/react-native';\n\n` +
185
+ ` // Auto-selects 'development' in dev, 'production' in release\n` +
186
+ ` // Auto-increments buildNumber on every release\n` +
187
+ ` await Upflux.init();\n\n` +
188
+ ` // Or specify a profile:\n` +
189
+ ` await Upflux.init('production');`));
190
+ }
191
+ // Security note about committing the file
192
+ console.log(chalk_1.default.cyan("\nšŸ’” Tip: upflux.json is safe to commit to git.\n" +
193
+ " upx_cli_* keys are read-only — they cannot publish releases.\n" +
194
+ " Only upx_pub_* publish keys should be kept secret.\n"));
195
+ });
196
+ exports.default = init;
@@ -21,7 +21,7 @@ function validateKeyFormat(key) {
21
21
  return false;
22
22
  }
23
23
  // Check for common publish key prefixes
24
- const validPrefixes = ["upflux_pub_", "upflux_cli_", "pk_"];
24
+ const validPrefixes = ["UPX-PUB-", "UPX-CLT-", "upx_pub_", "upx_cli_", "upflux_pub_", "upflux_cli_", "pk_"];
25
25
  const hasValidPrefix = validPrefixes.some(prefix => key.startsWith(prefix));
26
26
  // Also allow generic keys that are alphanumeric with underscores
27
27
  const isAlphanumeric = /^[a-zA-Z0-9_-]+$/.test(key);