@regressionproof/snapshotter 0.7.0 → 0.7.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.
Files changed (43) hide show
  1. package/build/Snapshotter.d.ts +11 -0
  2. package/build/Snapshotter.js +25 -0
  3. package/build/components/ErrorHandler.d.ts +9 -0
  4. package/build/components/ErrorHandler.js +46 -0
  5. package/build/components/FileSyncer.d.ts +8 -0
  6. package/build/{sync.js → components/FileSyncer.js} +30 -16
  7. package/build/components/TestResultsWriter.d.ts +7 -0
  8. package/build/components/TestResultsWriter.js +45 -0
  9. package/build/esm/Snapshotter.d.ts +11 -0
  10. package/build/esm/Snapshotter.js +20 -0
  11. package/build/esm/components/ErrorHandler.d.ts +9 -0
  12. package/build/esm/components/ErrorHandler.js +41 -0
  13. package/build/esm/components/FileSyncer.d.ts +8 -0
  14. package/build/esm/{sync.js → components/FileSyncer.js} +36 -17
  15. package/build/esm/components/TestResultsWriter.d.ts +7 -0
  16. package/build/esm/components/TestResultsWriter.js +33 -0
  17. package/build/esm/index.d.ts +2 -1
  18. package/build/esm/index.js +1 -1
  19. package/build/esm/scripts/runSnapshot.js +5 -64
  20. package/build/esm/scripts/testManual.js +4 -3
  21. package/build/esm/strategies/AsyncStrategy.d.ts +11 -0
  22. package/build/esm/strategies/AsyncStrategy.js +32 -0
  23. package/build/esm/strategies/SnapshotStrategy.d.ts +4 -0
  24. package/build/esm/strategies/SnapshotStrategy.js +1 -0
  25. package/build/esm/strategies/SyncStrategy.d.ts +8 -0
  26. package/build/esm/strategies/SyncStrategy.js +52 -0
  27. package/build/index.d.ts +2 -1
  28. package/build/index.js +6 -4
  29. package/build/scripts/runSnapshot.js +4 -68
  30. package/build/scripts/testManual.js +3 -2
  31. package/build/strategies/AsyncStrategy.d.ts +11 -0
  32. package/build/strategies/AsyncStrategy.js +38 -0
  33. package/build/strategies/SnapshotStrategy.d.ts +4 -0
  34. package/build/strategies/SnapshotStrategy.js +2 -0
  35. package/build/strategies/SyncStrategy.d.ts +8 -0
  36. package/build/strategies/SyncStrategy.js +46 -0
  37. package/package.json +2 -2
  38. package/build/esm/snapshot.d.ts +0 -3
  39. package/build/esm/snapshot.js +0 -40
  40. package/build/esm/sync.d.ts +0 -1
  41. package/build/snapshot.d.ts +0 -3
  42. package/build/snapshot.js +0 -47
  43. package/build/sync.d.ts +0 -1
@@ -0,0 +1,11 @@
1
+ import { SnapshotOptions } from './snapshotter.types.js';
2
+ export default class Snapshotter {
3
+ private strategy;
4
+ private constructor();
5
+ static Snapshotter(options?: SnapshotterOptions): Snapshotter;
6
+ snapshot(options: SnapshotOptions): void | Promise<void>;
7
+ checkForPreviousFailure(mirrorPath: string): void;
8
+ }
9
+ export interface SnapshotterOptions {
10
+ mode?: 'sync' | 'async';
11
+ }
@@ -0,0 +1,25 @@
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 ErrorHandler_js_1 = __importDefault(require("./components/ErrorHandler.js"));
7
+ const AsyncStrategy_js_1 = __importDefault(require("./strategies/AsyncStrategy.js"));
8
+ const SyncStrategy_js_1 = __importDefault(require("./strategies/SyncStrategy.js"));
9
+ class Snapshotter {
10
+ constructor(strategy) {
11
+ this.strategy = strategy;
12
+ }
13
+ static Snapshotter(options) {
14
+ const mode = options?.mode ?? 'async';
15
+ const strategy = mode === 'sync' ? SyncStrategy_js_1.default.Strategy() : AsyncStrategy_js_1.default.Strategy();
16
+ return new this(strategy);
17
+ }
18
+ snapshot(options) {
19
+ return this.strategy.execute(options);
20
+ }
21
+ checkForPreviousFailure(mirrorPath) {
22
+ ErrorHandler_js_1.default.Handler().checkForPreviousFailure(mirrorPath);
23
+ }
24
+ }
25
+ exports.default = Snapshotter;
@@ -0,0 +1,9 @@
1
+ export default class ErrorHandler {
2
+ private static readonly ERROR_FILE_NAME;
3
+ private constructor();
4
+ static Handler(): ErrorHandler;
5
+ checkForPreviousFailure(mirrorPath: string): void;
6
+ persistError(mirrorPath: string, err: unknown): void;
7
+ clearError(mirrorPath: string): void;
8
+ private getErrorFilePath;
9
+ }
@@ -0,0 +1,46 @@
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 fs_1 = require("fs");
7
+ const path_1 = __importDefault(require("path"));
8
+ class ErrorHandler {
9
+ constructor() { }
10
+ static Handler() {
11
+ return new this();
12
+ }
13
+ checkForPreviousFailure(mirrorPath) {
14
+ const errorPath = this.getErrorFilePath(mirrorPath);
15
+ if ((0, fs_1.existsSync)(errorPath)) {
16
+ const errorData = JSON.parse((0, fs_1.readFileSync)(errorPath, 'utf-8'));
17
+ (0, fs_1.unlinkSync)(errorPath);
18
+ throw new Error(`Previous snapshot failed: ${errorData.message}\n` +
19
+ `Timestamp: ${errorData.timestamp}\n` +
20
+ `This error was from a background snapshot that failed. ` +
21
+ `The snapshot has been retried - if this error persists, check your configuration.`);
22
+ }
23
+ }
24
+ persistError(mirrorPath, err) {
25
+ const snapshotterDir = path_1.default.join(mirrorPath, '.snapshotter');
26
+ (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
27
+ const errorPath = this.getErrorFilePath(mirrorPath);
28
+ const errorData = {
29
+ message: err instanceof Error ? err.message : String(err),
30
+ stack: err instanceof Error ? err.stack : undefined,
31
+ timestamp: new Date().toISOString(),
32
+ };
33
+ (0, fs_1.writeFileSync)(errorPath, JSON.stringify(errorData, null, 2));
34
+ }
35
+ clearError(mirrorPath) {
36
+ const errorPath = this.getErrorFilePath(mirrorPath);
37
+ if ((0, fs_1.existsSync)(errorPath)) {
38
+ (0, fs_1.unlinkSync)(errorPath);
39
+ }
40
+ }
41
+ getErrorFilePath(mirrorPath) {
42
+ return path_1.default.join(mirrorPath, '.snapshotter', ErrorHandler.ERROR_FILE_NAME);
43
+ }
44
+ }
45
+ ErrorHandler.ERROR_FILE_NAME = 'lastError.json';
46
+ exports.default = ErrorHandler;
@@ -0,0 +1,8 @@
1
+ export default class FileSyncer {
2
+ private static readonly DEFAULT_EXCLUDES;
3
+ private constructor();
4
+ static Syncer(): FileSyncer;
5
+ sync(sourcePath: string, mirrorPath: string): Promise<void>;
6
+ private syncWithGitIgnore;
7
+ private syncWithDelete;
8
+ }
@@ -3,13 +3,40 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.syncFiles = syncFiles;
7
6
  const child_process_1 = require("child_process");
8
7
  const fs_1 = require("fs");
9
8
  const path_1 = __importDefault(require("path"));
10
9
  const util_1 = require("util");
11
10
  const execAsync = (0, util_1.promisify)(child_process_1.exec);
12
- const DEFAULT_EXCLUDES = [
11
+ class FileSyncer {
12
+ constructor() { }
13
+ static Syncer() {
14
+ return new this();
15
+ }
16
+ async sync(sourcePath, mirrorPath) {
17
+ const hasGitIgnore = (0, fs_1.existsSync)(path_1.default.join(sourcePath, '.gitignore'));
18
+ const excludes = FileSyncer.DEFAULT_EXCLUDES.map((e) => `--exclude='${e}'`).join(' ');
19
+ if (hasGitIgnore) {
20
+ await this.syncWithGitIgnore(sourcePath, mirrorPath, excludes);
21
+ }
22
+ else {
23
+ await this.syncWithDelete(sourcePath, mirrorPath, excludes);
24
+ }
25
+ }
26
+ async syncWithGitIgnore(sourcePath, mirrorPath, excludes) {
27
+ // Filter through a file existence check to handle deleted files in git index
28
+ // This is more portable than --ignore-missing-args which isn't available on older rsync (macOS)
29
+ const cmd = `cd "${sourcePath}" && git ls-files --cached --others --exclude-standard -z | ` +
30
+ `while IFS= read -r -d '' file; do [ -e "$file" ] && printf '%s\\0' "$file"; done | ` +
31
+ `rsync -av --files-from=- --from0 ${excludes} . "${mirrorPath}/"`;
32
+ await execAsync(cmd);
33
+ }
34
+ async syncWithDelete(sourcePath, mirrorPath, excludes) {
35
+ const cmd = `rsync -av --delete ${excludes} "${sourcePath}/" "${mirrorPath}/"`;
36
+ await execAsync(cmd);
37
+ }
38
+ }
39
+ FileSyncer.DEFAULT_EXCLUDES = [
13
40
  'node_modules',
14
41
  'build',
15
42
  '*.env*',
@@ -21,17 +48,4 @@ const DEFAULT_EXCLUDES = [
21
48
  '*secret*',
22
49
  '*.local',
23
50
  ];
24
- async function syncFiles(sourcePath, mirrorPath) {
25
- const hasGitIgnore = (0, fs_1.existsSync)(path_1.default.join(sourcePath, '.gitignore'));
26
- const excludes = DEFAULT_EXCLUDES.map((e) => `--exclude='${e}'`).join(' ');
27
- if (hasGitIgnore) {
28
- // Filter through a file existence check to handle deleted files in git index
29
- // This is more portable than --ignore-missing-args which isn't available on older rsync (macOS)
30
- const cmd = `cd "${sourcePath}" && git ls-files --cached --others --exclude-standard -z | while IFS= read -r -d '' file; do [ -e "$file" ] && printf '%s\\0' "$file"; done | rsync -av --files-from=- --from0 ${excludes} . "${mirrorPath}/"`;
31
- await execAsync(cmd);
32
- }
33
- else {
34
- const cmd = `rsync -av --delete ${excludes} "${sourcePath}/" "${mirrorPath}/"`;
35
- await execAsync(cmd);
36
- }
37
- }
51
+ exports.default = FileSyncer;
@@ -0,0 +1,7 @@
1
+ import { TestResults } from '../snapshotter.types.js';
2
+ export default class TestResultsWriter {
3
+ private constructor();
4
+ static Writer(): TestResultsWriter;
5
+ write(mirrorPath: string, testResults: TestResults): void;
6
+ private sortTestResults;
7
+ }
@@ -0,0 +1,45 @@
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 fs_1 = require("fs");
7
+ const path_1 = __importDefault(require("path"));
8
+ class TestResultsWriter {
9
+ constructor() { }
10
+ static Writer() {
11
+ return new this();
12
+ }
13
+ write(mirrorPath, testResults) {
14
+ const snapshotterDir = path_1.default.join(mirrorPath, '.snapshotter');
15
+ (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
16
+ const sorted = this.sortTestResults(testResults);
17
+ (0, fs_1.writeFileSync)(path_1.default.join(snapshotterDir, 'testResults.json'), JSON.stringify(sorted, null, 2));
18
+ }
19
+ sortTestResults(testResults) {
20
+ const suites = [...testResults.suites].map((suite) => ({
21
+ ...suite,
22
+ tests: [...suite.tests].sort((left, right) => left.name.localeCompare(right.name)),
23
+ }));
24
+ suites.sort((left, right) => left.path.localeCompare(right.path));
25
+ const typeErrors = testResults.typeErrors
26
+ ? [...testResults.typeErrors].sort((left, right) => {
27
+ const fileCompare = left.file.localeCompare(right.file);
28
+ if (fileCompare !== 0) {
29
+ return fileCompare;
30
+ }
31
+ const lineCompare = left.line - right.line;
32
+ if (lineCompare !== 0) {
33
+ return lineCompare;
34
+ }
35
+ return left.column - right.column;
36
+ })
37
+ : undefined;
38
+ return {
39
+ ...testResults,
40
+ suites,
41
+ typeErrors,
42
+ };
43
+ }
44
+ }
45
+ exports.default = TestResultsWriter;
@@ -0,0 +1,11 @@
1
+ import { SnapshotOptions } from './snapshotter.types.js';
2
+ export default class Snapshotter {
3
+ private strategy;
4
+ private constructor();
5
+ static Snapshotter(options?: SnapshotterOptions): Snapshotter;
6
+ snapshot(options: SnapshotOptions): void | Promise<void>;
7
+ checkForPreviousFailure(mirrorPath: string): void;
8
+ }
9
+ export interface SnapshotterOptions {
10
+ mode?: 'sync' | 'async';
11
+ }
@@ -0,0 +1,20 @@
1
+ import ErrorHandler from './components/ErrorHandler.js.js';
2
+ import AsyncStrategy from './strategies/AsyncStrategy.js.js';
3
+ import SyncStrategy from './strategies/SyncStrategy.js.js';
4
+ export default class Snapshotter {
5
+ constructor(strategy) {
6
+ this.strategy = strategy;
7
+ }
8
+ static Snapshotter(options) {
9
+ var _a;
10
+ const mode = (_a = options === null || options === void 0 ? void 0 : options.mode) !== null && _a !== void 0 ? _a : 'async';
11
+ const strategy = mode === 'sync' ? SyncStrategy.Strategy() : AsyncStrategy.Strategy();
12
+ return new this(strategy);
13
+ }
14
+ snapshot(options) {
15
+ return this.strategy.execute(options);
16
+ }
17
+ checkForPreviousFailure(mirrorPath) {
18
+ ErrorHandler.Handler().checkForPreviousFailure(mirrorPath);
19
+ }
20
+ }
@@ -0,0 +1,9 @@
1
+ export default class ErrorHandler {
2
+ private static readonly ERROR_FILE_NAME;
3
+ private constructor();
4
+ static Handler(): ErrorHandler;
5
+ checkForPreviousFailure(mirrorPath: string): void;
6
+ persistError(mirrorPath: string, err: unknown): void;
7
+ clearError(mirrorPath: string): void;
8
+ private getErrorFilePath;
9
+ }
@@ -0,0 +1,41 @@
1
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from 'fs';
2
+ import path from 'path';
3
+ class ErrorHandler {
4
+ constructor() { }
5
+ static Handler() {
6
+ return new this();
7
+ }
8
+ checkForPreviousFailure(mirrorPath) {
9
+ const errorPath = this.getErrorFilePath(mirrorPath);
10
+ if (existsSync(errorPath)) {
11
+ const errorData = JSON.parse(readFileSync(errorPath, 'utf-8'));
12
+ unlinkSync(errorPath);
13
+ throw new Error(`Previous snapshot failed: ${errorData.message}\n` +
14
+ `Timestamp: ${errorData.timestamp}\n` +
15
+ `This error was from a background snapshot that failed. ` +
16
+ `The snapshot has been retried - if this error persists, check your configuration.`);
17
+ }
18
+ }
19
+ persistError(mirrorPath, err) {
20
+ const snapshotterDir = path.join(mirrorPath, '.snapshotter');
21
+ mkdirSync(snapshotterDir, { recursive: true });
22
+ const errorPath = this.getErrorFilePath(mirrorPath);
23
+ const errorData = {
24
+ message: err instanceof Error ? err.message : String(err),
25
+ stack: err instanceof Error ? err.stack : undefined,
26
+ timestamp: new Date().toISOString(),
27
+ };
28
+ writeFileSync(errorPath, JSON.stringify(errorData, null, 2));
29
+ }
30
+ clearError(mirrorPath) {
31
+ const errorPath = this.getErrorFilePath(mirrorPath);
32
+ if (existsSync(errorPath)) {
33
+ unlinkSync(errorPath);
34
+ }
35
+ }
36
+ getErrorFilePath(mirrorPath) {
37
+ return path.join(mirrorPath, '.snapshotter', ErrorHandler.ERROR_FILE_NAME);
38
+ }
39
+ }
40
+ ErrorHandler.ERROR_FILE_NAME = 'lastError.json';
41
+ export default ErrorHandler;
@@ -0,0 +1,8 @@
1
+ export default class FileSyncer {
2
+ private static readonly DEFAULT_EXCLUDES;
3
+ private constructor();
4
+ static Syncer(): FileSyncer;
5
+ sync(sourcePath: string, mirrorPath: string): Promise<void>;
6
+ private syncWithGitIgnore;
7
+ private syncWithDelete;
8
+ }
@@ -12,7 +12,41 @@ import { existsSync } from 'fs';
12
12
  import path from 'path';
13
13
  import { promisify } from 'util';
14
14
  const execAsync = promisify(exec);
15
- const DEFAULT_EXCLUDES = [
15
+ class FileSyncer {
16
+ constructor() { }
17
+ static Syncer() {
18
+ return new this();
19
+ }
20
+ sync(sourcePath, mirrorPath) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const hasGitIgnore = existsSync(path.join(sourcePath, '.gitignore'));
23
+ const excludes = FileSyncer.DEFAULT_EXCLUDES.map((e) => `--exclude='${e}'`).join(' ');
24
+ if (hasGitIgnore) {
25
+ yield this.syncWithGitIgnore(sourcePath, mirrorPath, excludes);
26
+ }
27
+ else {
28
+ yield this.syncWithDelete(sourcePath, mirrorPath, excludes);
29
+ }
30
+ });
31
+ }
32
+ syncWithGitIgnore(sourcePath, mirrorPath, excludes) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ // Filter through a file existence check to handle deleted files in git index
35
+ // This is more portable than --ignore-missing-args which isn't available on older rsync (macOS)
36
+ const cmd = `cd "${sourcePath}" && git ls-files --cached --others --exclude-standard -z | ` +
37
+ `while IFS= read -r -d '' file; do [ -e "$file" ] && printf '%s\\0' "$file"; done | ` +
38
+ `rsync -av --files-from=- --from0 ${excludes} . "${mirrorPath}/"`;
39
+ yield execAsync(cmd);
40
+ });
41
+ }
42
+ syncWithDelete(sourcePath, mirrorPath, excludes) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const cmd = `rsync -av --delete ${excludes} "${sourcePath}/" "${mirrorPath}/"`;
45
+ yield execAsync(cmd);
46
+ });
47
+ }
48
+ }
49
+ FileSyncer.DEFAULT_EXCLUDES = [
16
50
  'node_modules',
17
51
  'build',
18
52
  '*.env*',
@@ -24,19 +58,4 @@ const DEFAULT_EXCLUDES = [
24
58
  '*secret*',
25
59
  '*.local',
26
60
  ];
27
- export function syncFiles(sourcePath, mirrorPath) {
28
- return __awaiter(this, void 0, void 0, function* () {
29
- const hasGitIgnore = existsSync(path.join(sourcePath, '.gitignore'));
30
- const excludes = DEFAULT_EXCLUDES.map((e) => `--exclude='${e}'`).join(' ');
31
- if (hasGitIgnore) {
32
- // Filter through a file existence check to handle deleted files in git index
33
- // This is more portable than --ignore-missing-args which isn't available on older rsync (macOS)
34
- const cmd = `cd "${sourcePath}" && git ls-files --cached --others --exclude-standard -z | while IFS= read -r -d '' file; do [ -e "$file" ] && printf '%s\\0' "$file"; done | rsync -av --files-from=- --from0 ${excludes} . "${mirrorPath}/"`;
35
- yield execAsync(cmd);
36
- }
37
- else {
38
- const cmd = `rsync -av --delete ${excludes} "${sourcePath}/" "${mirrorPath}/"`;
39
- yield execAsync(cmd);
40
- }
41
- });
42
- }
61
+ export default FileSyncer;
@@ -0,0 +1,7 @@
1
+ import { TestResults } from '../snapshotter.types.js';
2
+ export default class TestResultsWriter {
3
+ private constructor();
4
+ static Writer(): TestResultsWriter;
5
+ write(mirrorPath: string, testResults: TestResults): void;
6
+ private sortTestResults;
7
+ }
@@ -0,0 +1,33 @@
1
+ import { mkdirSync, writeFileSync } from 'fs';
2
+ import path from 'path';
3
+ export default class TestResultsWriter {
4
+ constructor() { }
5
+ static Writer() {
6
+ return new this();
7
+ }
8
+ write(mirrorPath, testResults) {
9
+ const snapshotterDir = path.join(mirrorPath, '.snapshotter');
10
+ mkdirSync(snapshotterDir, { recursive: true });
11
+ const sorted = this.sortTestResults(testResults);
12
+ writeFileSync(path.join(snapshotterDir, 'testResults.json'), JSON.stringify(sorted, null, 2));
13
+ }
14
+ sortTestResults(testResults) {
15
+ const suites = [...testResults.suites].map((suite) => (Object.assign(Object.assign({}, suite), { tests: [...suite.tests].sort((left, right) => left.name.localeCompare(right.name)) })));
16
+ suites.sort((left, right) => left.path.localeCompare(right.path));
17
+ const typeErrors = testResults.typeErrors
18
+ ? [...testResults.typeErrors].sort((left, right) => {
19
+ const fileCompare = left.file.localeCompare(right.file);
20
+ if (fileCompare !== 0) {
21
+ return fileCompare;
22
+ }
23
+ const lineCompare = left.line - right.line;
24
+ if (lineCompare !== 0) {
25
+ return lineCompare;
26
+ }
27
+ return left.column - right.column;
28
+ })
29
+ : undefined;
30
+ return Object.assign(Object.assign({}, testResults), { suites,
31
+ typeErrors });
32
+ }
33
+ }
@@ -1,2 +1,3 @@
1
- export { snapshot, checkForPreviousSnapshotFailure } from './snapshot.js';
1
+ export { default as Snapshotter } from './Snapshotter.js';
2
+ export type { SnapshotterOptions } from './Snapshotter.js';
2
3
  export * from './snapshotter.types.js';
@@ -1,2 +1,2 @@
1
- export { snapshot, checkForPreviousSnapshotFailure } from './snapshot.js.js';
1
+ export { default as Snapshotter } from './Snapshotter.js.js';
2
2
  export * from './snapshotter.types.js.js';
@@ -7,12 +7,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from 'fs';
10
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
11
11
  import path from 'path';
12
12
  import { buildLog } from '@sprucelabs/spruce-skill-utils';
13
- import { gitCommit, gitPush } from '../git.js.js';
14
- import { syncFiles } from '../sync.js.js';
15
- const ERROR_FILE_NAME = 'lastError.json';
13
+ import ErrorHandler from '../components/ErrorHandler.js.js';
14
+ import SyncStrategy from '../strategies/SyncStrategy.js.js';
16
15
  const LOCK_FILE_NAME = 'snapshot.lock';
17
16
  const PENDING_FILE_NAME = 'pending.json';
18
17
  const log = buildLog('Snapshotter');
@@ -51,74 +50,16 @@ function processLoop(snapshotterDir) {
51
50
  }
52
51
  function executeSnapshot(options) {
53
52
  return __awaiter(this, void 0, void 0, function* () {
54
- var _a;
55
- const sourcePath = (_a = options.sourcePath) !== null && _a !== void 0 ? _a : process.cwd();
56
- const { mirrorPath, testResults, remote } = options;
57
- log.info('Starting snapshot', sourcePath, mirrorPath);
58
53
  try {
59
- yield syncFiles(sourcePath, mirrorPath);
60
- log.info('Files synced', mirrorPath);
61
- const snapshotterDir = path.join(mirrorPath, '.snapshotter');
62
- mkdirSync(snapshotterDir, { recursive: true });
63
- writeFileSync(path.join(snapshotterDir, 'testResults.json'), JSON.stringify(sortTestResults(testResults), null, 2));
64
- log.info('Test results saved', snapshotterDir);
65
- const committed = yield gitCommit(mirrorPath, log);
66
- if (!committed) {
67
- log.info('No changes to commit', mirrorPath);
68
- clearError(mirrorPath);
69
- return;
70
- }
71
- log.info('Commit created, pushing', remote.url);
72
- yield gitPush(mirrorPath, remote, log);
73
- log.info('Push completed', remote.url);
74
- clearError(mirrorPath);
54
+ yield SyncStrategy.Strategy().execute(options);
75
55
  }
76
56
  catch (err) {
77
57
  const message = err instanceof Error ? err.message : String(err);
78
58
  log.error('Snapshot failed (will surface on next test run)', message);
79
- persistError(mirrorPath, err);
59
+ ErrorHandler.Handler().persistError(options.mirrorPath, err);
80
60
  }
81
61
  });
82
62
  }
83
- function persistError(mirrorPath, err) {
84
- const snapshotterDir = path.join(mirrorPath, '.snapshotter');
85
- mkdirSync(snapshotterDir, { recursive: true });
86
- const errorPath = getErrorFilePath(mirrorPath);
87
- const errorData = {
88
- message: err instanceof Error ? err.message : String(err),
89
- stack: err instanceof Error ? err.stack : undefined,
90
- timestamp: new Date().toISOString(),
91
- };
92
- writeFileSync(errorPath, JSON.stringify(errorData, null, 2));
93
- }
94
- function clearError(mirrorPath) {
95
- const errorPath = getErrorFilePath(mirrorPath);
96
- if (existsSync(errorPath)) {
97
- unlinkSync(errorPath);
98
- }
99
- }
100
- function getErrorFilePath(mirrorPath) {
101
- return path.join(mirrorPath, '.snapshotter', ERROR_FILE_NAME);
102
- }
103
- function sortTestResults(testResults) {
104
- const suites = [...testResults.suites].map((suite) => (Object.assign(Object.assign({}, suite), { tests: [...suite.tests].sort((left, right) => left.name.localeCompare(right.name)) })));
105
- suites.sort((left, right) => left.path.localeCompare(right.path));
106
- const typeErrors = testResults.typeErrors
107
- ? [...testResults.typeErrors].sort((left, right) => {
108
- const fileCompare = left.file.localeCompare(right.file);
109
- if (fileCompare !== 0) {
110
- return fileCompare;
111
- }
112
- const lineCompare = left.line - right.line;
113
- if (lineCompare !== 0) {
114
- return lineCompare;
115
- }
116
- return left.column - right.column;
117
- })
118
- : undefined;
119
- return Object.assign(Object.assign({}, testResults), { suites,
120
- typeErrors });
121
- }
122
63
  main().catch((err) => {
123
64
  console.error('Snapshot script failed:', err);
124
65
  process.exit(1);
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { snapshot } from '../index.js';
10
+ import { Snapshotter } from '../index.js';
11
11
  function main() {
12
12
  return __awaiter(this, void 0, void 0, function* () {
13
13
  const sourcePath = process.env.SOURCE_PATH;
@@ -22,7 +22,8 @@ function main() {
22
22
  console.log(' Source:', sourcePath);
23
23
  console.log(' Mirror:', mirrorPath);
24
24
  console.log(' Remote:', remoteUrl);
25
- const result = yield snapshot({
25
+ const snapshotter = Snapshotter.Snapshotter({ mode: 'sync' });
26
+ yield snapshotter.snapshot({
26
27
  sourcePath,
27
28
  mirrorPath,
28
29
  testResults: {
@@ -51,7 +52,7 @@ function main() {
51
52
  token: remoteToken,
52
53
  },
53
54
  });
54
- console.log('Snapshot created:', result);
55
+ console.log('Snapshot completed');
55
56
  });
56
57
  }
57
58
  main().catch((err) => {
@@ -0,0 +1,11 @@
1
+ import { SnapshotOptions } from '../snapshotter.types.js';
2
+ import SnapshotStrategy from './SnapshotStrategy.js';
3
+ export default class AsyncStrategy implements SnapshotStrategy {
4
+ private log;
5
+ private scriptPath;
6
+ private constructor();
7
+ static Strategy(): AsyncStrategy;
8
+ execute(options: SnapshotOptions): void;
9
+ private writeOptionsFile;
10
+ private spawnSnapshotProcess;
11
+ }
@@ -0,0 +1,32 @@
1
+ import { spawn } from 'child_process';
2
+ import { mkdirSync, writeFileSync } from 'fs';
3
+ import path from 'path';
4
+ import { buildLog } from '@sprucelabs/spruce-skill-utils';
5
+ export default class AsyncStrategy {
6
+ constructor() {
7
+ this.log = buildLog('Snapshotter');
8
+ this.scriptPath = path.join(__dirname, '..', 'scripts', 'runSnapshot.js');
9
+ }
10
+ static Strategy() {
11
+ return new this();
12
+ }
13
+ execute(options) {
14
+ const snapshotterDir = this.writeOptionsFile(options);
15
+ this.spawnSnapshotProcess(snapshotterDir);
16
+ this.log.info('Snapshot queued (running in background)', options.mirrorPath);
17
+ }
18
+ writeOptionsFile(options) {
19
+ const snapshotterDir = path.join(options.mirrorPath, '.snapshotter');
20
+ mkdirSync(snapshotterDir, { recursive: true });
21
+ const optionsPath = path.join(snapshotterDir, 'pending.json');
22
+ writeFileSync(optionsPath, JSON.stringify(options, null, 2));
23
+ return snapshotterDir;
24
+ }
25
+ spawnSnapshotProcess(snapshotterDir) {
26
+ const child = spawn('node', [this.scriptPath, snapshotterDir], {
27
+ detached: true,
28
+ stdio: 'ignore',
29
+ });
30
+ child.unref();
31
+ }
32
+ }
@@ -0,0 +1,4 @@
1
+ import { SnapshotOptions } from '../snapshotter.types.js';
2
+ export default interface SnapshotStrategy {
3
+ execute(options: SnapshotOptions): Promise<void> | void;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { SnapshotOptions } from '../snapshotter.types.js';
2
+ import SnapshotStrategy from './SnapshotStrategy.js';
3
+ export default class SyncStrategy implements SnapshotStrategy {
4
+ private log;
5
+ private constructor();
6
+ static Strategy(): SyncStrategy;
7
+ execute(options: SnapshotOptions): Promise<void>;
8
+ }
@@ -0,0 +1,52 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { buildLog } from '@sprucelabs/spruce-skill-utils';
11
+ import ErrorHandler from '../components/ErrorHandler.js.js';
12
+ import FileSyncer from '../components/FileSyncer.js.js';
13
+ import TestResultsWriter from '../components/TestResultsWriter.js.js';
14
+ import { gitCommit, gitPush } from '../git.js.js';
15
+ export default class SyncStrategy {
16
+ constructor() {
17
+ this.log = buildLog('Snapshotter');
18
+ }
19
+ static Strategy() {
20
+ return new this();
21
+ }
22
+ execute(options) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ var _a;
25
+ const sourcePath = (_a = options.sourcePath) !== null && _a !== void 0 ? _a : process.cwd();
26
+ const { mirrorPath, testResults, remote } = options;
27
+ this.log.info('Starting snapshot', sourcePath, mirrorPath);
28
+ try {
29
+ yield FileSyncer.Syncer().sync(sourcePath, mirrorPath);
30
+ this.log.info('Files synced', mirrorPath);
31
+ TestResultsWriter.Writer().write(mirrorPath, testResults);
32
+ this.log.info('Test results saved', mirrorPath);
33
+ const committed = yield gitCommit(mirrorPath, this.log);
34
+ if (!committed) {
35
+ this.log.info('No changes to commit', mirrorPath);
36
+ ErrorHandler.Handler().clearError(mirrorPath);
37
+ return;
38
+ }
39
+ this.log.info('Commit created, pushing', remote.url);
40
+ yield gitPush(mirrorPath, remote, this.log);
41
+ this.log.info('Push completed', remote.url);
42
+ ErrorHandler.Handler().clearError(mirrorPath);
43
+ }
44
+ catch (err) {
45
+ const message = err instanceof Error ? err.message : String(err);
46
+ this.log.error('Snapshot failed', message);
47
+ ErrorHandler.Handler().persistError(mirrorPath, err);
48
+ throw err;
49
+ }
50
+ });
51
+ }
52
+ }
package/build/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export { snapshot, checkForPreviousSnapshotFailure } from './snapshot.js';
1
+ export { default as Snapshotter } from './Snapshotter.js';
2
+ export type { SnapshotterOptions } from './Snapshotter.js';
2
3
  export * from './snapshotter.types.js';
package/build/index.js CHANGED
@@ -13,9 +13,11 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
13
13
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
16
19
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.checkForPreviousSnapshotFailure = exports.snapshot = void 0;
18
- var snapshot_js_1 = require("./snapshot.js");
19
- Object.defineProperty(exports, "snapshot", { enumerable: true, get: function () { return snapshot_js_1.snapshot; } });
20
- Object.defineProperty(exports, "checkForPreviousSnapshotFailure", { enumerable: true, get: function () { return snapshot_js_1.checkForPreviousSnapshotFailure; } });
20
+ exports.Snapshotter = void 0;
21
+ var Snapshotter_js_1 = require("./Snapshotter.js");
22
+ Object.defineProperty(exports, "Snapshotter", { enumerable: true, get: function () { return __importDefault(Snapshotter_js_1).default; } });
21
23
  __exportStar(require("./snapshotter.types.js"), exports);
@@ -6,9 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_1 = require("fs");
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
9
- const git_js_1 = require("../git.js");
10
- const sync_js_1 = require("../sync.js");
11
- const ERROR_FILE_NAME = 'lastError.json';
9
+ const ErrorHandler_js_1 = __importDefault(require("../components/ErrorHandler.js"));
10
+ const SyncStrategy_js_1 = __importDefault(require("../strategies/SyncStrategy.js"));
12
11
  const LOCK_FILE_NAME = 'snapshot.lock';
13
12
  const PENDING_FILE_NAME = 'pending.json';
14
13
  const log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
@@ -42,78 +41,15 @@ async function processLoop(snapshotterDir) {
42
41
  }
43
42
  }
44
43
  async function executeSnapshot(options) {
45
- const sourcePath = options.sourcePath ?? process.cwd();
46
- const { mirrorPath, testResults, remote } = options;
47
- log.info('Starting snapshot', sourcePath, mirrorPath);
48
44
  try {
49
- await (0, sync_js_1.syncFiles)(sourcePath, mirrorPath);
50
- log.info('Files synced', mirrorPath);
51
- const snapshotterDir = path_1.default.join(mirrorPath, '.snapshotter');
52
- (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
53
- (0, fs_1.writeFileSync)(path_1.default.join(snapshotterDir, 'testResults.json'), JSON.stringify(sortTestResults(testResults), null, 2));
54
- log.info('Test results saved', snapshotterDir);
55
- const committed = await (0, git_js_1.gitCommit)(mirrorPath, log);
56
- if (!committed) {
57
- log.info('No changes to commit', mirrorPath);
58
- clearError(mirrorPath);
59
- return;
60
- }
61
- log.info('Commit created, pushing', remote.url);
62
- await (0, git_js_1.gitPush)(mirrorPath, remote, log);
63
- log.info('Push completed', remote.url);
64
- clearError(mirrorPath);
45
+ await SyncStrategy_js_1.default.Strategy().execute(options);
65
46
  }
66
47
  catch (err) {
67
48
  const message = err instanceof Error ? err.message : String(err);
68
49
  log.error('Snapshot failed (will surface on next test run)', message);
69
- persistError(mirrorPath, err);
70
- }
71
- }
72
- function persistError(mirrorPath, err) {
73
- const snapshotterDir = path_1.default.join(mirrorPath, '.snapshotter');
74
- (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
75
- const errorPath = getErrorFilePath(mirrorPath);
76
- const errorData = {
77
- message: err instanceof Error ? err.message : String(err),
78
- stack: err instanceof Error ? err.stack : undefined,
79
- timestamp: new Date().toISOString(),
80
- };
81
- (0, fs_1.writeFileSync)(errorPath, JSON.stringify(errorData, null, 2));
82
- }
83
- function clearError(mirrorPath) {
84
- const errorPath = getErrorFilePath(mirrorPath);
85
- if ((0, fs_1.existsSync)(errorPath)) {
86
- (0, fs_1.unlinkSync)(errorPath);
50
+ ErrorHandler_js_1.default.Handler().persistError(options.mirrorPath, err);
87
51
  }
88
52
  }
89
- function getErrorFilePath(mirrorPath) {
90
- return path_1.default.join(mirrorPath, '.snapshotter', ERROR_FILE_NAME);
91
- }
92
- function sortTestResults(testResults) {
93
- const suites = [...testResults.suites].map((suite) => ({
94
- ...suite,
95
- tests: [...suite.tests].sort((left, right) => left.name.localeCompare(right.name)),
96
- }));
97
- suites.sort((left, right) => left.path.localeCompare(right.path));
98
- const typeErrors = testResults.typeErrors
99
- ? [...testResults.typeErrors].sort((left, right) => {
100
- const fileCompare = left.file.localeCompare(right.file);
101
- if (fileCompare !== 0) {
102
- return fileCompare;
103
- }
104
- const lineCompare = left.line - right.line;
105
- if (lineCompare !== 0) {
106
- return lineCompare;
107
- }
108
- return left.column - right.column;
109
- })
110
- : undefined;
111
- return {
112
- ...testResults,
113
- suites,
114
- typeErrors,
115
- };
116
- }
117
53
  main().catch((err) => {
118
54
  console.error('Snapshot script failed:', err);
119
55
  process.exit(1);
@@ -14,7 +14,8 @@ async function main() {
14
14
  console.log(' Source:', sourcePath);
15
15
  console.log(' Mirror:', mirrorPath);
16
16
  console.log(' Remote:', remoteUrl);
17
- const result = await (0, index_1.snapshot)({
17
+ const snapshotter = index_1.Snapshotter.Snapshotter({ mode: 'sync' });
18
+ await snapshotter.snapshot({
18
19
  sourcePath,
19
20
  mirrorPath,
20
21
  testResults: {
@@ -43,7 +44,7 @@ async function main() {
43
44
  token: remoteToken,
44
45
  },
45
46
  });
46
- console.log('Snapshot created:', result);
47
+ console.log('Snapshot completed');
47
48
  }
48
49
  main().catch((err) => {
49
50
  console.error('Error:', err.message);
@@ -0,0 +1,11 @@
1
+ import { SnapshotOptions } from '../snapshotter.types.js';
2
+ import SnapshotStrategy from './SnapshotStrategy.js';
3
+ export default class AsyncStrategy implements SnapshotStrategy {
4
+ private log;
5
+ private scriptPath;
6
+ private constructor();
7
+ static Strategy(): AsyncStrategy;
8
+ execute(options: SnapshotOptions): void;
9
+ private writeOptionsFile;
10
+ private spawnSnapshotProcess;
11
+ }
@@ -0,0 +1,38 @@
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 child_process_1 = require("child_process");
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
10
+ class AsyncStrategy {
11
+ constructor() {
12
+ this.log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
13
+ this.scriptPath = path_1.default.join(__dirname, '..', 'scripts', 'runSnapshot.js');
14
+ }
15
+ static Strategy() {
16
+ return new this();
17
+ }
18
+ execute(options) {
19
+ const snapshotterDir = this.writeOptionsFile(options);
20
+ this.spawnSnapshotProcess(snapshotterDir);
21
+ this.log.info('Snapshot queued (running in background)', options.mirrorPath);
22
+ }
23
+ writeOptionsFile(options) {
24
+ const snapshotterDir = path_1.default.join(options.mirrorPath, '.snapshotter');
25
+ (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
26
+ const optionsPath = path_1.default.join(snapshotterDir, 'pending.json');
27
+ (0, fs_1.writeFileSync)(optionsPath, JSON.stringify(options, null, 2));
28
+ return snapshotterDir;
29
+ }
30
+ spawnSnapshotProcess(snapshotterDir) {
31
+ const child = (0, child_process_1.spawn)('node', [this.scriptPath, snapshotterDir], {
32
+ detached: true,
33
+ stdio: 'ignore',
34
+ });
35
+ child.unref();
36
+ }
37
+ }
38
+ exports.default = AsyncStrategy;
@@ -0,0 +1,4 @@
1
+ import { SnapshotOptions } from '../snapshotter.types.js';
2
+ export default interface SnapshotStrategy {
3
+ execute(options: SnapshotOptions): Promise<void> | void;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import { SnapshotOptions } from '../snapshotter.types.js';
2
+ import SnapshotStrategy from './SnapshotStrategy.js';
3
+ export default class SyncStrategy implements SnapshotStrategy {
4
+ private log;
5
+ private constructor();
6
+ static Strategy(): SyncStrategy;
7
+ execute(options: SnapshotOptions): Promise<void>;
8
+ }
@@ -0,0 +1,46 @@
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 spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
7
+ const ErrorHandler_js_1 = __importDefault(require("../components/ErrorHandler.js"));
8
+ const FileSyncer_js_1 = __importDefault(require("../components/FileSyncer.js"));
9
+ const TestResultsWriter_js_1 = __importDefault(require("../components/TestResultsWriter.js"));
10
+ const git_js_1 = require("../git.js");
11
+ class SyncStrategy {
12
+ constructor() {
13
+ this.log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
14
+ }
15
+ static Strategy() {
16
+ return new this();
17
+ }
18
+ async execute(options) {
19
+ const sourcePath = options.sourcePath ?? process.cwd();
20
+ const { mirrorPath, testResults, remote } = options;
21
+ this.log.info('Starting snapshot', sourcePath, mirrorPath);
22
+ try {
23
+ await FileSyncer_js_1.default.Syncer().sync(sourcePath, mirrorPath);
24
+ this.log.info('Files synced', mirrorPath);
25
+ TestResultsWriter_js_1.default.Writer().write(mirrorPath, testResults);
26
+ this.log.info('Test results saved', mirrorPath);
27
+ const committed = await (0, git_js_1.gitCommit)(mirrorPath, this.log);
28
+ if (!committed) {
29
+ this.log.info('No changes to commit', mirrorPath);
30
+ ErrorHandler_js_1.default.Handler().clearError(mirrorPath);
31
+ return;
32
+ }
33
+ this.log.info('Commit created, pushing', remote.url);
34
+ await (0, git_js_1.gitPush)(mirrorPath, remote, this.log);
35
+ this.log.info('Push completed', remote.url);
36
+ ErrorHandler_js_1.default.Handler().clearError(mirrorPath);
37
+ }
38
+ catch (err) {
39
+ const message = err instanceof Error ? err.message : String(err);
40
+ this.log.error('Snapshot failed', message);
41
+ ErrorHandler_js_1.default.Handler().persistError(mirrorPath, err);
42
+ throw err;
43
+ }
44
+ }
45
+ }
46
+ exports.default = SyncStrategy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@regressionproof/snapshotter",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -94,5 +94,5 @@
94
94
  "@sprucelabs/spruce-core-schemas": "^42.1.3",
95
95
  "@sprucelabs/spruce-skill-utils": "^34.0.3"
96
96
  },
97
- "gitHead": "860c3695ab884487c654e5cf794262bff8ea1570"
97
+ "gitHead": "c38dea336a4653790787044ca8b4209a9e5352fa"
98
98
  }
@@ -1,3 +0,0 @@
1
- import { SnapshotOptions } from './snapshotter.types.js';
2
- export declare function snapshot(options: SnapshotOptions): void;
3
- export declare function checkForPreviousSnapshotFailure(mirrorPath: string): void;
@@ -1,40 +0,0 @@
1
- import { spawn } from 'child_process';
2
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from 'fs';
3
- import path from 'path';
4
- import { buildLog } from '@sprucelabs/spruce-skill-utils';
5
- const ERROR_FILE_NAME = 'lastError.json';
6
- const log = buildLog('Snapshotter');
7
- const scriptPath = path.join(__dirname, 'scripts', 'runSnapshot.js');
8
- export function snapshot(options) {
9
- const snapshotterDir = writeOptionsFile(options);
10
- spawnSnapshotProcess(snapshotterDir);
11
- log.info('Snapshot queued (running in background)', options.mirrorPath);
12
- }
13
- export function checkForPreviousSnapshotFailure(mirrorPath) {
14
- const errorPath = getErrorFilePath(mirrorPath);
15
- if (existsSync(errorPath)) {
16
- const errorData = JSON.parse(readFileSync(errorPath, 'utf-8'));
17
- unlinkSync(errorPath);
18
- throw new Error(`Previous snapshot failed: ${errorData.message}\n` +
19
- `Timestamp: ${errorData.timestamp}\n` +
20
- `This error was from a background snapshot that failed. ` +
21
- `The snapshot has been retried - if this error persists, check your configuration.`);
22
- }
23
- }
24
- function writeOptionsFile(options) {
25
- const snapshotterDir = path.join(options.mirrorPath, '.snapshotter');
26
- mkdirSync(snapshotterDir, { recursive: true });
27
- const optionsPath = path.join(snapshotterDir, 'pending.json');
28
- writeFileSync(optionsPath, JSON.stringify(options, null, 2));
29
- return snapshotterDir;
30
- }
31
- function spawnSnapshotProcess(snapshotterDir) {
32
- const child = spawn('node', [scriptPath, snapshotterDir], {
33
- detached: true,
34
- stdio: 'ignore',
35
- });
36
- child.unref();
37
- }
38
- function getErrorFilePath(mirrorPath) {
39
- return path.join(mirrorPath, '.snapshotter', ERROR_FILE_NAME);
40
- }
@@ -1 +0,0 @@
1
- export declare function syncFiles(sourcePath: string, mirrorPath: string): Promise<void>;
@@ -1,3 +0,0 @@
1
- import { SnapshotOptions } from './snapshotter.types.js';
2
- export declare function snapshot(options: SnapshotOptions): void;
3
- export declare function checkForPreviousSnapshotFailure(mirrorPath: string): void;
package/build/snapshot.js DELETED
@@ -1,47 +0,0 @@
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.snapshot = snapshot;
7
- exports.checkForPreviousSnapshotFailure = checkForPreviousSnapshotFailure;
8
- const child_process_1 = require("child_process");
9
- const fs_1 = require("fs");
10
- const path_1 = __importDefault(require("path"));
11
- const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
12
- const ERROR_FILE_NAME = 'lastError.json';
13
- const log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
14
- const scriptPath = path_1.default.join(__dirname, 'scripts', 'runSnapshot.js');
15
- function snapshot(options) {
16
- const snapshotterDir = writeOptionsFile(options);
17
- spawnSnapshotProcess(snapshotterDir);
18
- log.info('Snapshot queued (running in background)', options.mirrorPath);
19
- }
20
- function checkForPreviousSnapshotFailure(mirrorPath) {
21
- const errorPath = getErrorFilePath(mirrorPath);
22
- if ((0, fs_1.existsSync)(errorPath)) {
23
- const errorData = JSON.parse((0, fs_1.readFileSync)(errorPath, 'utf-8'));
24
- (0, fs_1.unlinkSync)(errorPath);
25
- throw new Error(`Previous snapshot failed: ${errorData.message}\n` +
26
- `Timestamp: ${errorData.timestamp}\n` +
27
- `This error was from a background snapshot that failed. ` +
28
- `The snapshot has been retried - if this error persists, check your configuration.`);
29
- }
30
- }
31
- function writeOptionsFile(options) {
32
- const snapshotterDir = path_1.default.join(options.mirrorPath, '.snapshotter');
33
- (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
34
- const optionsPath = path_1.default.join(snapshotterDir, 'pending.json');
35
- (0, fs_1.writeFileSync)(optionsPath, JSON.stringify(options, null, 2));
36
- return snapshotterDir;
37
- }
38
- function spawnSnapshotProcess(snapshotterDir) {
39
- const child = (0, child_process_1.spawn)('node', [scriptPath, snapshotterDir], {
40
- detached: true,
41
- stdio: 'ignore',
42
- });
43
- child.unref();
44
- }
45
- function getErrorFilePath(mirrorPath) {
46
- return path_1.default.join(mirrorPath, '.snapshotter', ERROR_FILE_NAME);
47
- }
package/build/sync.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function syncFiles(sourcePath: string, mirrorPath: string): Promise<void>;