hostfn 0.1.4 → 0.1.7
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/LICENSE +21 -0
- package/README.md +1 -2
- package/dist/index.js +7 -1
- package/package.json +18 -6
- package/src/__tests__/core/sync.test.ts +42 -0
- package/src/__tests__/core/workspace.test.ts +180 -0
- package/src/commands/deploy.ts +122 -83
- package/src/commands/init.ts +1 -1
- package/src/config/loader.ts +1 -1
- package/src/config/schema.ts +1 -1
- package/src/core/ssh.ts +2 -0
- package/src/core/sync.ts +64 -23
- package/src/core/workspace.ts +111 -6
- package/src/index.ts +8 -1
- package/dist/__tests__/core/backup.test.d.ts +0 -2
- package/dist/__tests__/core/backup.test.d.ts.map +0 -1
- package/dist/__tests__/core/backup.test.js +0 -108
- package/dist/__tests__/core/backup.test.js.map +0 -1
- package/dist/__tests__/core/health.test.d.ts +0 -2
- package/dist/__tests__/core/health.test.d.ts.map +0 -1
- package/dist/__tests__/core/health.test.js +0 -97
- package/dist/__tests__/core/health.test.js.map +0 -1
- package/dist/__tests__/core/lock.test.d.ts +0 -2
- package/dist/__tests__/core/lock.test.d.ts.map +0 -1
- package/dist/__tests__/core/lock.test.js +0 -136
- package/dist/__tests__/core/lock.test.js.map +0 -1
- package/dist/__tests__/core/nginx-multi-domain.test.d.ts +0 -2
- package/dist/__tests__/core/nginx-multi-domain.test.d.ts.map +0 -1
- package/dist/__tests__/core/nginx-multi-domain.test.js +0 -158
- package/dist/__tests__/core/nginx-multi-domain.test.js.map +0 -1
- package/dist/__tests__/runtimes/pm2.test.d.ts +0 -2
- package/dist/__tests__/runtimes/pm2.test.d.ts.map +0 -1
- package/dist/__tests__/runtimes/pm2.test.js +0 -111
- package/dist/__tests__/runtimes/pm2.test.js.map +0 -1
- package/dist/__tests__/utils/validation.test.d.ts +0 -2
- package/dist/__tests__/utils/validation.test.d.ts.map +0 -1
- package/dist/__tests__/utils/validation.test.js +0 -136
- package/dist/__tests__/utils/validation.test.js.map +0 -1
- package/dist/commands/deploy.d.ts +0 -11
- package/dist/commands/deploy.d.ts.map +0 -1
- package/dist/commands/deploy.js +0 -636
- package/dist/commands/deploy.js.map +0 -1
- package/dist/commands/env.d.ts +0 -21
- package/dist/commands/env.d.ts.map +0 -1
- package/dist/commands/env.js +0 -317
- package/dist/commands/env.js.map +0 -1
- package/dist/commands/expose.d.ts +0 -6
- package/dist/commands/expose.d.ts.map +0 -1
- package/dist/commands/expose.js +0 -379
- package/dist/commands/expose.js.map +0 -1
- package/dist/commands/init.d.ts +0 -2
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -175
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/logs.d.ts +0 -10
- package/dist/commands/logs.d.ts.map +0 -1
- package/dist/commands/logs.js +0 -75
- package/dist/commands/logs.js.map +0 -1
- package/dist/commands/rollback.d.ts +0 -6
- package/dist/commands/rollback.d.ts.map +0 -1
- package/dist/commands/rollback.js +0 -113
- package/dist/commands/rollback.js.map +0 -1
- package/dist/commands/server/info.d.ts +0 -2
- package/dist/commands/server/info.d.ts.map +0 -1
- package/dist/commands/server/info.js +0 -104
- package/dist/commands/server/info.js.map +0 -1
- package/dist/commands/server/setup.d.ts +0 -11
- package/dist/commands/server/setup.d.ts.map +0 -1
- package/dist/commands/server/setup.js +0 -161
- package/dist/commands/server/setup.js.map +0 -1
- package/dist/commands/status.d.ts +0 -6
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js +0 -120
- package/dist/commands/status.js.map +0 -1
- package/dist/config/loader.d.ts +0 -21
- package/dist/config/loader.d.ts.map +0 -1
- package/dist/config/loader.js +0 -54
- package/dist/config/loader.js.map +0 -1
- package/dist/config/schema.d.ts +0 -323
- package/dist/config/schema.d.ts.map +0 -1
- package/dist/config/schema.js +0 -108
- package/dist/config/schema.js.map +0 -1
- package/dist/core/backup.d.ts +0 -34
- package/dist/core/backup.d.ts.map +0 -1
- package/dist/core/backup.js +0 -95
- package/dist/core/backup.js.map +0 -1
- package/dist/core/health.d.ts +0 -31
- package/dist/core/health.d.ts.map +0 -1
- package/dist/core/health.js +0 -78
- package/dist/core/health.js.map +0 -1
- package/dist/core/local.d.ts +0 -19
- package/dist/core/local.d.ts.map +0 -1
- package/dist/core/local.js +0 -50
- package/dist/core/local.js.map +0 -1
- package/dist/core/lock.d.ts +0 -28
- package/dist/core/lock.d.ts.map +0 -1
- package/dist/core/lock.js +0 -89
- package/dist/core/lock.js.map +0 -1
- package/dist/core/nginx.d.ts +0 -43
- package/dist/core/nginx.d.ts.map +0 -1
- package/dist/core/nginx.js +0 -131
- package/dist/core/nginx.js.map +0 -1
- package/dist/core/ssh.d.ts +0 -79
- package/dist/core/ssh.d.ts.map +0 -1
- package/dist/core/ssh.js +0 -264
- package/dist/core/ssh.js.map +0 -1
- package/dist/core/sync.d.ts +0 -25
- package/dist/core/sync.d.ts.map +0 -1
- package/dist/core/sync.js +0 -117
- package/dist/core/sync.js.map +0 -1
- package/dist/core/workspace.d.ts +0 -13
- package/dist/core/workspace.d.ts.map +0 -1
- package/dist/core/workspace.js +0 -141
- package/dist/core/workspace.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/runtimes/base.d.ts +0 -115
- package/dist/runtimes/base.d.ts.map +0 -1
- package/dist/runtimes/base.js +0 -16
- package/dist/runtimes/base.js.map +0 -1
- package/dist/runtimes/nodejs/detector.d.ts +0 -47
- package/dist/runtimes/nodejs/detector.d.ts.map +0 -1
- package/dist/runtimes/nodejs/detector.js +0 -143
- package/dist/runtimes/nodejs/detector.js.map +0 -1
- package/dist/runtimes/nodejs/index.d.ts +0 -14
- package/dist/runtimes/nodejs/index.d.ts.map +0 -1
- package/dist/runtimes/nodejs/index.js +0 -213
- package/dist/runtimes/nodejs/index.js.map +0 -1
- package/dist/runtimes/nodejs/pm2.d.ts +0 -17
- package/dist/runtimes/nodejs/pm2.d.ts.map +0 -1
- package/dist/runtimes/nodejs/pm2.js +0 -60
- package/dist/runtimes/nodejs/pm2.js.map +0 -1
- package/dist/runtimes/registry.d.ts +0 -34
- package/dist/runtimes/registry.d.ts.map +0 -1
- package/dist/runtimes/registry.js +0 -58
- package/dist/runtimes/registry.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -47
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -76
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -32
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -125
- package/dist/utils/validation.js.map +0 -1
package/src/core/sync.ts
CHANGED
|
@@ -12,6 +12,31 @@ export interface SyncOptions {
|
|
|
12
12
|
* Sync files to remote server using rsync
|
|
13
13
|
*/
|
|
14
14
|
export class FileSync {
|
|
15
|
+
private static buildBaseArgs(options: SyncOptions = {}): string[] {
|
|
16
|
+
const args = [
|
|
17
|
+
'-avz',
|
|
18
|
+
'--delete',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
if (options.dryRun) {
|
|
22
|
+
args.push('--dry-run');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (options.include && options.include.length > 0) {
|
|
26
|
+
for (const pattern of options.include) {
|
|
27
|
+
args.push('--include', pattern);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (options.exclude && options.exclude.length > 0) {
|
|
32
|
+
for (const pattern of options.exclude) {
|
|
33
|
+
args.push('--exclude', pattern);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return args;
|
|
38
|
+
}
|
|
39
|
+
|
|
15
40
|
/**
|
|
16
41
|
* Sync local directory to remote server
|
|
17
42
|
*/
|
|
@@ -21,10 +46,7 @@ export class FileSync {
|
|
|
21
46
|
sshConnection: string, // user@host
|
|
22
47
|
options: SyncOptions = {}
|
|
23
48
|
): Promise<void> {
|
|
24
|
-
const args =
|
|
25
|
-
'-avz', // archive, verbose, compress
|
|
26
|
-
'--delete', // delete files on remote that don't exist locally
|
|
27
|
-
];
|
|
49
|
+
const args = this.buildBaseArgs(options);
|
|
28
50
|
|
|
29
51
|
// Handle SSH authentication for CI/CD mode
|
|
30
52
|
let tempKeyPath: string | undefined;
|
|
@@ -49,25 +71,6 @@ export class FileSync {
|
|
|
49
71
|
args.push('-e', 'ssh -o StrictHostKeyChecking=no -o BatchMode=yes');
|
|
50
72
|
}
|
|
51
73
|
|
|
52
|
-
// Add dry-run flag
|
|
53
|
-
if (options.dryRun) {
|
|
54
|
-
args.push('--dry-run');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Add exclude patterns
|
|
58
|
-
if (options.exclude && options.exclude.length > 0) {
|
|
59
|
-
for (const pattern of options.exclude) {
|
|
60
|
-
args.push('--exclude', pattern);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Add include patterns
|
|
65
|
-
if (options.include && options.include.length > 0) {
|
|
66
|
-
for (const pattern of options.include) {
|
|
67
|
-
args.push('--include', pattern);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
74
|
// Ensure trailing slash on source (rsync behavior)
|
|
72
75
|
const source = localPath.endsWith('/') ? localPath : `${localPath}/`;
|
|
73
76
|
const destination = `${sshConnection}:${remotePath}`;
|
|
@@ -111,6 +114,44 @@ export class FileSync {
|
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Sync local directory to another local directory using the same rsync rules
|
|
119
|
+
* as remote deploys.
|
|
120
|
+
*/
|
|
121
|
+
static async syncLocal(
|
|
122
|
+
sourcePath: string,
|
|
123
|
+
destinationPath: string,
|
|
124
|
+
options: SyncOptions = {}
|
|
125
|
+
): Promise<void> {
|
|
126
|
+
const args = this.buildBaseArgs(options);
|
|
127
|
+
const source = sourcePath.endsWith('/') ? sourcePath : `${sourcePath}/`;
|
|
128
|
+
|
|
129
|
+
args.push(source, destinationPath);
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const result = await execa('rsync', args, {
|
|
133
|
+
stdio: options.verbose ? 'inherit' : 'pipe',
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (result.exitCode !== 0) {
|
|
137
|
+
throw new Error(`rsync failed with exit code ${result.exitCode}`);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (error instanceof Error) {
|
|
141
|
+
if (error.message.includes('ENOENT') || error.message.includes('not found')) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
'rsync is not installed on your system.\n' +
|
|
144
|
+
'Please install it:\n' +
|
|
145
|
+
' - macOS: brew install rsync\n' +
|
|
146
|
+
' - Ubuntu/Debian: apt-get install rsync\n' +
|
|
147
|
+
' - Windows: Install via WSL or use Git Bash'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
114
155
|
/**
|
|
115
156
|
* Check if rsync is available
|
|
116
157
|
*/
|
package/src/core/workspace.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, existsSync, cpSync, mkdirSync } from 'fs';
|
|
2
|
-
import { join, dirname, resolve } from 'path';
|
|
2
|
+
import { join, dirname, resolve, relative, sep } from 'path';
|
|
3
|
+
import { valid, validRange, satisfies } from 'semver';
|
|
3
4
|
import { Logger } from '../utils/logger.js';
|
|
4
5
|
|
|
5
6
|
interface PackageJson {
|
|
@@ -95,8 +96,11 @@ export class WorkspaceManager {
|
|
|
95
96
|
|
|
96
97
|
Logger.info(`Bundling ${workspaceDeps.length} workspace dependencies...`);
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
// Store workspace deps in __workspace__/ (not node_modules/) so they are:
|
|
100
|
+
// 1. Included in the main rsync (not excluded like node_modules)
|
|
101
|
+
// 2. Not wiped out when npm ci/install cleans node_modules
|
|
102
|
+
const workspaceDir = join(targetDir, '__workspace__');
|
|
103
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
100
104
|
|
|
101
105
|
for (const depName of workspaceDeps) {
|
|
102
106
|
const depPath = this.workspacePackages.get(depName);
|
|
@@ -113,7 +117,7 @@ export class WorkspaceManager {
|
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
const targetDepDir = join(
|
|
120
|
+
const targetDepDir = join(workspaceDir, depName);
|
|
117
121
|
|
|
118
122
|
mkdirSync(dirname(targetDepDir), { recursive: true });
|
|
119
123
|
|
|
@@ -130,6 +134,55 @@ export class WorkspaceManager {
|
|
|
130
134
|
}
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
async generateLockfile(targetDir: string, servicePath?: string): Promise<void> {
|
|
138
|
+
const { execSync } = await import('child_process');
|
|
139
|
+
const pkgJsonPath = join(targetDir, 'package.json');
|
|
140
|
+
|
|
141
|
+
// Temporarily pin direct dependencies to their exact resolved versions from the
|
|
142
|
+
// root monorepo lockfile. Without this, `npm install --package-lock-only` would
|
|
143
|
+
// re-resolve all dependencies from the npm registry and may pick up newer
|
|
144
|
+
// (potentially breaking) versions (e.g. better-auth 1.3.x → 1.5.x).
|
|
145
|
+
//
|
|
146
|
+
// We pin direct deps only (not transitive). Overriding transitive deps causes
|
|
147
|
+
// EUSAGE errors from `npm ci` because the lockfile's transitive versions may no
|
|
148
|
+
// longer match what the pinned direct dep's own package.json requires.
|
|
149
|
+
if (this.workspaceRoot) {
|
|
150
|
+
const rootLockfilePath = join(this.workspaceRoot, 'package-lock.json');
|
|
151
|
+
if (existsSync(rootLockfilePath)) {
|
|
152
|
+
try {
|
|
153
|
+
const rootLockfile = JSON.parse(readFileSync(rootLockfilePath, 'utf-8'));
|
|
154
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
155
|
+
|
|
156
|
+
// Replace semver ranges in direct deps with the exact resolved version.
|
|
157
|
+
// This prevents npm from upgrading direct deps when generating the lockfile.
|
|
158
|
+
for (const depGroup of ['dependencies', 'devDependencies'] as const) {
|
|
159
|
+
for (const depName of Object.keys(pkg[depGroup] || {})) {
|
|
160
|
+
const declaredVersion = pkg[depGroup]![depName];
|
|
161
|
+
const exactVersion = this.getResolvedVersionForDependency(
|
|
162
|
+
rootLockfile.packages || {},
|
|
163
|
+
servicePath,
|
|
164
|
+
depName,
|
|
165
|
+
declaredVersion,
|
|
166
|
+
);
|
|
167
|
+
if (exactVersion) {
|
|
168
|
+
pkg[depGroup]![depName] = exactVersion;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2));
|
|
174
|
+
} catch {
|
|
175
|
+
// Fall through without pinning
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
execSync('npm install --package-lock-only --ignore-scripts', {
|
|
181
|
+
cwd: targetDir,
|
|
182
|
+
stdio: 'ignore',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
133
186
|
rewritePackageJson(servicePath: string, targetDir: string): void {
|
|
134
187
|
const workspaceDeps = this.getWorkspaceDependencies(servicePath);
|
|
135
188
|
|
|
@@ -143,7 +196,7 @@ export class WorkspaceManager {
|
|
|
143
196
|
if (pkg.dependencies) {
|
|
144
197
|
for (const depName of workspaceDeps) {
|
|
145
198
|
if (pkg.dependencies[depName]) {
|
|
146
|
-
pkg.dependencies[depName] = `file:./
|
|
199
|
+
pkg.dependencies[depName] = `file:./__workspace__/${depName}`;
|
|
147
200
|
}
|
|
148
201
|
}
|
|
149
202
|
}
|
|
@@ -151,7 +204,7 @@ export class WorkspaceManager {
|
|
|
151
204
|
if (pkg.devDependencies) {
|
|
152
205
|
for (const depName of workspaceDeps) {
|
|
153
206
|
if (pkg.devDependencies[depName]) {
|
|
154
|
-
|
|
207
|
+
pkg.devDependencies[depName] = `file:./__workspace__/${depName}`;
|
|
155
208
|
}
|
|
156
209
|
}
|
|
157
210
|
}
|
|
@@ -177,4 +230,56 @@ export class WorkspaceManager {
|
|
|
177
230
|
isInWorkspace(): boolean {
|
|
178
231
|
return this.workspaceRoot !== null;
|
|
179
232
|
}
|
|
233
|
+
|
|
234
|
+
private getResolvedVersionForDependency(
|
|
235
|
+
lockfilePackages: Record<string, { version?: string; name?: string }>,
|
|
236
|
+
servicePath: string | undefined,
|
|
237
|
+
depName: string,
|
|
238
|
+
declaredRange: string,
|
|
239
|
+
): string | null {
|
|
240
|
+
const candidatePaths = this.getDependencyCandidatePaths(servicePath, depName);
|
|
241
|
+
|
|
242
|
+
for (const candidatePath of candidatePaths) {
|
|
243
|
+
const pkgEntry = lockfilePackages[candidatePath];
|
|
244
|
+
if (!pkgEntry?.version) continue;
|
|
245
|
+
if (pkgEntry.name !== undefined && pkgEntry.name !== depName) continue;
|
|
246
|
+
if (!this.isResolvedVersionCompatible(declaredRange, pkgEntry.version)) continue;
|
|
247
|
+
return pkgEntry.version;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private getDependencyCandidatePaths(servicePath: string | undefined, depName: string): string[] {
|
|
254
|
+
const candidates: string[] = [];
|
|
255
|
+
|
|
256
|
+
if (this.workspaceRoot && servicePath) {
|
|
257
|
+
const relativeServicePath = relative(this.workspaceRoot, servicePath).split(sep).join('/');
|
|
258
|
+
if (relativeServicePath && relativeServicePath !== '.') {
|
|
259
|
+
candidates.push(`${relativeServicePath}/node_modules/${depName}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
candidates.push(`node_modules/${depName}`);
|
|
264
|
+
return candidates;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private isResolvedVersionCompatible(declaredRange: string, resolvedVersion: string): boolean {
|
|
268
|
+
const normalizedRange = declaredRange.startsWith('workspace:')
|
|
269
|
+
? declaredRange.slice('workspace:'.length)
|
|
270
|
+
: declaredRange;
|
|
271
|
+
|
|
272
|
+
if (normalizedRange === '' || normalizedRange === '*') {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const validResolvedVersion = valid(resolvedVersion);
|
|
277
|
+
const validResolvedRange = validRange(normalizedRange);
|
|
278
|
+
|
|
279
|
+
if (!validResolvedVersion || !validResolvedRange) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return satisfies(validResolvedVersion, validResolvedRange);
|
|
284
|
+
}
|
|
180
285
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,13 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { Logger } from './utils/logger.js';
|
|
5
5
|
import { RuntimeRegistry } from './runtimes/registry.js';
|
|
6
6
|
import { NodeJSAdapter } from './runtimes/nodejs/index.js';
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
7
14
|
|
|
8
15
|
// Register runtime adapters
|
|
9
16
|
RuntimeRegistry.register(new NodeJSAdapter());
|
|
@@ -13,7 +20,7 @@ const program = new Command();
|
|
|
13
20
|
program
|
|
14
21
|
.name('hostfn')
|
|
15
22
|
.description('Universal application deployment CLI')
|
|
16
|
-
.version(
|
|
23
|
+
.version(packageJson.version);
|
|
17
24
|
|
|
18
25
|
// Init command
|
|
19
26
|
program
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backup.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/core/backup.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { BackupManager } from '../../core/backup.js';
|
|
3
|
-
// Mock SSH connection
|
|
4
|
-
const mockSSH = {
|
|
5
|
-
exec: vi.fn(),
|
|
6
|
-
exists: vi.fn(),
|
|
7
|
-
mkdir: vi.fn(),
|
|
8
|
-
upload: vi.fn(),
|
|
9
|
-
download: vi.fn(),
|
|
10
|
-
disconnect: vi.fn(),
|
|
11
|
-
};
|
|
12
|
-
describe('BackupManager', () => {
|
|
13
|
-
let backupManager;
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks();
|
|
16
|
-
backupManager = new BackupManager(mockSSH, '/var/www/myapp');
|
|
17
|
-
});
|
|
18
|
-
describe('create', () => {
|
|
19
|
-
it('should create backup with timestamp', async () => {
|
|
20
|
-
mockSSH.mkdir.mockResolvedValue(undefined);
|
|
21
|
-
mockSSH.exists.mockResolvedValue(true); // dist exists
|
|
22
|
-
mockSSH.exec.mockResolvedValue({ stdout: '', stderr: '', exitCode: 0 });
|
|
23
|
-
const backupPath = await backupManager.create();
|
|
24
|
-
expect(backupPath).toMatch(/\/var\/www\/myapp\/backups\/\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}/);
|
|
25
|
-
expect(mockSSH.mkdir).toHaveBeenCalled();
|
|
26
|
-
expect(mockSSH.exec).toHaveBeenCalled();
|
|
27
|
-
});
|
|
28
|
-
it('should return path even if source directory does not exist', async () => {
|
|
29
|
-
mockSSH.mkdir.mockResolvedValue(undefined);
|
|
30
|
-
mockSSH.exists.mockResolvedValue(false); // No dist directory
|
|
31
|
-
const backupPath = await backupManager.create();
|
|
32
|
-
// Returns backup path but doesn't fail
|
|
33
|
-
expect(backupPath).toMatch(/\/var\/www\/myapp\/backups\/\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}/);
|
|
34
|
-
expect(mockSSH.mkdir).toHaveBeenCalled();
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
describe('list', () => {
|
|
38
|
-
it('should list all backups with timestamps', async () => {
|
|
39
|
-
mockSSH.exists.mockResolvedValue(true);
|
|
40
|
-
mockSSH.exec.mockResolvedValue({
|
|
41
|
-
stdout: 'myapp.backup.20251114_130000\nmyapp.backup.20251114_120000\n', // sorted reverse
|
|
42
|
-
stderr: '',
|
|
43
|
-
exitCode: 0
|
|
44
|
-
});
|
|
45
|
-
const backups = await backupManager.list();
|
|
46
|
-
expect(backups).toHaveLength(2);
|
|
47
|
-
expect(backups[0]).toContain('20251114_130000'); // Most recent first
|
|
48
|
-
expect(backups[1]).toContain('20251114_120000');
|
|
49
|
-
});
|
|
50
|
-
it('should return empty array when no backups exist', async () => {
|
|
51
|
-
mockSSH.exec.mockResolvedValue({
|
|
52
|
-
stdout: '',
|
|
53
|
-
stderr: '',
|
|
54
|
-
exitCode: 0
|
|
55
|
-
});
|
|
56
|
-
const backups = await backupManager.list();
|
|
57
|
-
expect(backups).toHaveLength(0);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
describe('restore', () => {
|
|
61
|
-
it('should restore from backup', async () => {
|
|
62
|
-
mockSSH.exists.mockResolvedValue(true);
|
|
63
|
-
mockSSH.exec.mockResolvedValue({ stdout: '', stderr: '', exitCode: 0 });
|
|
64
|
-
await backupManager.restore('myapp.backup.20251114_120000');
|
|
65
|
-
expect(mockSSH.exec).toHaveBeenCalledWith(expect.stringContaining('cp -r'));
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
describe('cleanup', () => {
|
|
69
|
-
it('should keep only specified number of backups', async () => {
|
|
70
|
-
const backupNames = [
|
|
71
|
-
'myapp.backup.20251114_150000', // Most recent (sorted)
|
|
72
|
-
'myapp.backup.20251114_140000',
|
|
73
|
-
'myapp.backup.20251114_130000',
|
|
74
|
-
'myapp.backup.20251114_120000',
|
|
75
|
-
'myapp.backup.20251114_110000',
|
|
76
|
-
'myapp.backup.20251114_100000', // Oldest
|
|
77
|
-
];
|
|
78
|
-
mockSSH.exists.mockResolvedValue(true);
|
|
79
|
-
mockSSH.exec
|
|
80
|
-
.mockResolvedValueOnce({
|
|
81
|
-
stdout: backupNames.join('\n'),
|
|
82
|
-
stderr: '',
|
|
83
|
-
exitCode: 0
|
|
84
|
-
})
|
|
85
|
-
.mockResolvedValue({ stdout: '', stderr: '', exitCode: 0 });
|
|
86
|
-
await backupManager.cleanup(3);
|
|
87
|
-
// Should remove oldest 3 backups
|
|
88
|
-
expect(mockSSH.exec).toHaveBeenCalledWith(expect.stringContaining('rm -rf'));
|
|
89
|
-
});
|
|
90
|
-
it('should not remove backups if under limit', async () => {
|
|
91
|
-
const backupNames = [
|
|
92
|
-
'myapp.backup.20251114_100000',
|
|
93
|
-
'myapp.backup.20251114_110000',
|
|
94
|
-
];
|
|
95
|
-
mockSSH.exists.mockResolvedValue(true);
|
|
96
|
-
mockSSH.exec.mockResolvedValueOnce({
|
|
97
|
-
stdout: backupNames.join('\n'),
|
|
98
|
-
stderr: '',
|
|
99
|
-
exitCode: 0
|
|
100
|
-
});
|
|
101
|
-
await backupManager.cleanup(5);
|
|
102
|
-
// Should only call list, not remove (called twice: exists + ls)
|
|
103
|
-
expect(mockSSH.exec).toHaveBeenCalledTimes(1);
|
|
104
|
-
expect(mockSSH.exec).toHaveBeenCalledWith(expect.stringContaining('ls -1'));
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
//# sourceMappingURL=backup.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backup.test.js","sourceRoot":"","sources":["../../../src/__tests__/core/backup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/core/health.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { HealthCheck } from '../../core/health.js';
|
|
3
|
-
// Mock fetch globally
|
|
4
|
-
global.fetch = vi.fn();
|
|
5
|
-
describe('HealthCheck', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
vi.clearAllMocks();
|
|
8
|
-
});
|
|
9
|
-
describe('check', () => {
|
|
10
|
-
it('should return healthy for successful response', async () => {
|
|
11
|
-
global.fetch.mockResolvedValueOnce({
|
|
12
|
-
ok: true,
|
|
13
|
-
status: 200,
|
|
14
|
-
});
|
|
15
|
-
const result = await HealthCheck.check({
|
|
16
|
-
url: 'http://localhost:3000/health',
|
|
17
|
-
});
|
|
18
|
-
expect(result.healthy).toBe(true);
|
|
19
|
-
expect(result.statusCode).toBe(200);
|
|
20
|
-
expect(result.responseTime).toBeGreaterThanOrEqual(0);
|
|
21
|
-
});
|
|
22
|
-
it('should return unhealthy for failed response', async () => {
|
|
23
|
-
global.fetch.mockResolvedValueOnce({
|
|
24
|
-
ok: false,
|
|
25
|
-
status: 500,
|
|
26
|
-
});
|
|
27
|
-
const result = await HealthCheck.check({
|
|
28
|
-
url: 'http://localhost:3000/health',
|
|
29
|
-
});
|
|
30
|
-
expect(result.healthy).toBe(false);
|
|
31
|
-
expect(result.statusCode).toBe(500);
|
|
32
|
-
});
|
|
33
|
-
it('should return unhealthy for network error', async () => {
|
|
34
|
-
global.fetch.mockRejectedValueOnce(new Error('Network error'));
|
|
35
|
-
const result = await HealthCheck.check({
|
|
36
|
-
url: 'http://localhost:3000/health',
|
|
37
|
-
});
|
|
38
|
-
expect(result.healthy).toBe(false);
|
|
39
|
-
expect(result.error).toBeDefined();
|
|
40
|
-
});
|
|
41
|
-
it('should respect timeout', async () => {
|
|
42
|
-
global.fetch.mockImplementationOnce(() => new Promise((resolve) => setTimeout(resolve, 2000)));
|
|
43
|
-
const result = await HealthCheck.check({
|
|
44
|
-
url: 'http://localhost:3000/health',
|
|
45
|
-
timeout: 100,
|
|
46
|
-
});
|
|
47
|
-
expect(result.healthy).toBe(false);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
describe('waitForReady', () => {
|
|
51
|
-
it('should return true when service becomes healthy', async () => {
|
|
52
|
-
let callCount = 0;
|
|
53
|
-
global.fetch.mockImplementation(() => {
|
|
54
|
-
callCount++;
|
|
55
|
-
return Promise.resolve({
|
|
56
|
-
ok: callCount >= 2, // Becomes healthy on second call
|
|
57
|
-
status: callCount >= 2 ? 200 : 503,
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
const result = await HealthCheck.waitForReady({
|
|
61
|
-
url: 'http://localhost:3000/health',
|
|
62
|
-
retries: 5,
|
|
63
|
-
interval: 10,
|
|
64
|
-
});
|
|
65
|
-
expect(result).toBe(true);
|
|
66
|
-
expect(callCount).toBeGreaterThanOrEqual(2);
|
|
67
|
-
});
|
|
68
|
-
it('should return false when max retries exceeded', async () => {
|
|
69
|
-
global.fetch.mockResolvedValue({
|
|
70
|
-
ok: false,
|
|
71
|
-
status: 503,
|
|
72
|
-
});
|
|
73
|
-
const result = await HealthCheck.waitForReady({
|
|
74
|
-
url: 'http://localhost:3000/health',
|
|
75
|
-
retries: 2,
|
|
76
|
-
interval: 10,
|
|
77
|
-
});
|
|
78
|
-
expect(result).toBe(false);
|
|
79
|
-
});
|
|
80
|
-
it('should call progress callback on each attempt', async () => {
|
|
81
|
-
global.fetch.mockResolvedValue({
|
|
82
|
-
ok: false,
|
|
83
|
-
status: 503,
|
|
84
|
-
});
|
|
85
|
-
const progressCalls = [];
|
|
86
|
-
await HealthCheck.waitForReady({
|
|
87
|
-
url: 'http://localhost:3000/health',
|
|
88
|
-
retries: 3,
|
|
89
|
-
interval: 10,
|
|
90
|
-
}, (attempt) => {
|
|
91
|
-
progressCalls.push(attempt);
|
|
92
|
-
});
|
|
93
|
-
expect(progressCalls).toEqual([1, 2, 3]);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
//# sourceMappingURL=health.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health.test.js","sourceRoot":"","sources":["../../../src/__tests__/core/health.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lock.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/core/lock.test.ts"],"names":[],"mappings":""}
|