cloud-ide-cide 2.0.34 → 2.0.35

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.
@@ -4,10 +4,9 @@
4
4
  *
5
5
  * Reads config from: ../.cide/config.json (token, paths)
6
6
  * Writes state to: ../.cide/deployments.json
7
- * Stores releases in: ../.cide/releases/{appCode}/{version}/
8
- * Stores backups in: ../.cide/backups/{appCode}/{version}.zip
7
+ * Extracts code to: {server_root}/{appCode}/ (live app directory)
8
+ * Stores zips in: ../.cide/releases/{appCode}/{version}.zip (for rollback)
9
9
  * Logs to: ../.cide/logs/deploy.log
10
- * Symlinks: {server_root}/current/{appCode} → active release
11
10
  *
12
11
  * Endpoints (all except /health require Authorization: Bearer <token>):
13
12
  *
@@ -36,9 +35,7 @@ try { config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')); } catch { /* no
36
35
  const TOKEN = config.token || process.env.CIDE_UPLOAD_TOKEN || '';
37
36
  const PORT = process.env.CIDE_UPLOAD_PORT || process.env.PORT || 4500;
38
37
  const RELEASES = config.paths?.releases || path.join(CIDE_DIR, 'releases');
39
- const BACKUPS = config.paths?.backups || path.join(CIDE_DIR, 'backups');
40
38
  const LOGS = config.paths?.logs || path.join(CIDE_DIR, 'logs');
41
- const CURRENT_DIR = config.paths?.current || path.join(path.dirname(CIDE_DIR), 'current');
42
39
  const DEPLOYMENTS = path.join(CIDE_DIR, 'deployments.json');
43
40
 
44
41
  const upload = multer({ dest: path.join(CIDE_DIR, 'tmp') });
@@ -59,37 +56,6 @@ function appendLog(message) {
59
56
  try { fs.appendFileSync(logFile, line); } catch { /* logs dir may not exist yet */ }
60
57
  }
61
58
 
62
- function switchCurrent(currentPath, releasePath) {
63
- fs.mkdirSync(path.dirname(currentPath), { recursive: true });
64
- try {
65
- const stat = fs.lstatSync(currentPath);
66
- if (stat.isSymbolicLink()) {
67
- fs.unlinkSync(currentPath);
68
- } else if (stat.isDirectory()) {
69
- fs.renameSync(currentPath, `${currentPath}_bak_${Date.now()}`);
70
- }
71
- } catch { /* doesn't exist yet */ }
72
-
73
- try {
74
- fs.symlinkSync(releasePath, currentPath, 'junction');
75
- } catch {
76
- copyRecursive(releasePath, currentPath);
77
- }
78
- }
79
-
80
- function copyRecursive(src, dst) {
81
- fs.mkdirSync(dst, { recursive: true });
82
- for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
83
- const srcPath = path.join(src, entry.name);
84
- const dstPath = path.join(dst, entry.name);
85
- if (entry.isDirectory()) {
86
- copyRecursive(srcPath, dstPath);
87
- } else {
88
- fs.copyFileSync(srcPath, dstPath);
89
- }
90
- }
91
- }
92
-
93
59
  // ── Auth middleware ───────────────────────────────────────────────────────────
94
60
  function authGuard(req, res, next) {
95
61
  if (!TOKEN) {
@@ -103,6 +69,9 @@ function authGuard(req, res, next) {
103
69
  next();
104
70
  }
105
71
 
72
+ // ── Server root (parent of .cide/) ───────────────────────────────────────────
73
+ const SERVER_ROOT = config.serverRoot || path.dirname(CIDE_DIR);
74
+
106
75
  // ═══════════════════════════════════════════════════════════════════════════════
107
76
  // ── Upload ────────────────────────────────────────────────────────────────────
108
77
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -122,31 +91,32 @@ app.post('/upload', authGuard, upload.single('file'), (req, res) => {
122
91
  }
123
92
 
124
93
  const version = new Date().toISOString().replace(/[:.]/g, '-').replace('T', '_').slice(0, 19);
125
- const releasePath = path.join(RELEASES, appCode, version);
126
- const currentPath = path.join(CURRENT_DIR, appCode);
127
94
 
128
- // ── Save backup zip ──────────────────────────────────────────────────
129
- const backupDir = path.join(BACKUPS, appCode);
130
- fs.mkdirSync(backupDir, { recursive: true });
131
- fs.copyFileSync(req.file.path, path.join(backupDir, `${version}.zip`));
95
+ // ── Live app directory at server root ────────────────────────────────
96
+ const appDir = path.join(SERVER_ROOT, appCode);
97
+
98
+ // ── Save zip to releases for rollback ────────────────────────────────
99
+ const releaseDir = path.join(RELEASES, appCode);
100
+ fs.mkdirSync(releaseDir, { recursive: true });
101
+ const releaseZipPath = path.join(releaseDir, `${version}.zip`);
102
+ fs.copyFileSync(req.file.path, releaseZipPath);
132
103
 
133
- // ── Extract ──────────────────────────────────────────────────────────
104
+ // ── Extract directly to {server_root}/{appCode}/ ─────────────────────
105
+ fs.mkdirSync(appDir, { recursive: true });
134
106
  const zip = new AdmZip(req.file.path);
135
- fs.mkdirSync(releasePath, { recursive: true });
136
- zip.extractAllTo(releasePath, true);
107
+ zip.extractAllTo(appDir, true);
137
108
  fs.unlinkSync(req.file.path);
138
109
 
139
110
  // ── Track state ──────────────────────────────────────────────────────
140
111
  const deployments = loadDeployments();
141
112
  const previousVersion = deployments.apps?.[appCode]?.current?.version || null;
142
113
 
143
- switchCurrent(currentPath, releasePath);
144
-
145
114
  // ── Record ───────────────────────────────────────────────────────────
146
115
  const record = {
147
116
  version,
148
117
  environment,
149
- releasePath,
118
+ appDir,
119
+ releaseZip: releaseZipPath,
150
120
  deployedAt: new Date().toISOString(),
151
121
  action: 'upload',
152
122
  message: deployMsg,
@@ -169,7 +139,8 @@ app.post('/upload', authGuard, upload.single('file'), (req, res) => {
169
139
  environment,
170
140
  releaseVersion: version,
171
141
  previousVersion,
172
- releasePath,
142
+ appDir,
143
+ releaseZip: releaseZipPath,
173
144
  completedAt: new Date().toISOString(),
174
145
  });
175
146
  } catch (err) {
@@ -211,21 +182,25 @@ app.post('/rollback', authGuard, (req, res) => {
211
182
  return res.status(422).json({ status: 'FAILED', message: 'Missing required fields: appCode, version' });
212
183
  }
213
184
 
214
- const releasePath = path.join(RELEASES, appCode, version);
215
- if (!fs.existsSync(releasePath)) {
216
- return res.status(404).json({ status: 'FAILED', message: `Release not found: ${version}` });
185
+ const releaseZipPath = path.join(RELEASES, appCode, `${version}.zip`);
186
+ if (!fs.existsSync(releaseZipPath)) {
187
+ return res.status(404).json({ status: 'FAILED', message: `Release zip not found: ${version}` });
217
188
  }
218
189
 
219
- const currentPath = path.join(CURRENT_DIR, appCode);
190
+ const appDir = path.join(SERVER_ROOT, appCode);
220
191
  const deployments = loadDeployments();
221
192
  const previousVersion = deployments.apps?.[appCode]?.current?.version || null;
222
193
 
223
- switchCurrent(currentPath, releasePath);
194
+ // Re-extract the zip to the app directory
195
+ fs.mkdirSync(appDir, { recursive: true });
196
+ const zip = new AdmZip(releaseZipPath);
197
+ zip.extractAllTo(appDir, true);
224
198
 
225
199
  const record = {
226
200
  version,
227
201
  environment: deployments.apps?.[appCode]?.current?.environment || 'production',
228
- releasePath,
202
+ appDir,
203
+ releaseZip: releaseZipPath,
229
204
  deployedAt: new Date().toISOString(),
230
205
  action: 'rollback',
231
206
  previousVersion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloud-ide-cide",
3
- "version": "2.0.34",
3
+ "version": "2.0.35",
4
4
  "description": "Cloud IDE CLI — create, build, publish, upload and deploy Cloud IDE projects.",
5
5
  "main": "cli.js",
6
6
  "bin": {