@lumy-pack/syncpoint 0.0.4 → 0.0.5
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/assets/config.default.yml +15 -7
- package/assets/schemas/config.schema.json +68 -0
- package/assets/schemas/metadata.schema.json +121 -0
- package/assets/schemas/template.schema.json +61 -0
- package/assets/template.example.yml +6 -5
- package/dist/cli.mjs +634 -242
- package/dist/commands/Migrate.d.ts +2 -0
- package/dist/core/migrate.d.ts +11 -0
- package/dist/index.cjs +215 -74
- package/dist/index.mjs +215 -74
- package/dist/utils/types.d.ts +10 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -76,6 +76,76 @@ function getSubDir(sub) {
|
|
|
76
76
|
return join2(getAppDir(), sub);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// assets/schemas/config.schema.json
|
|
80
|
+
var config_schema_default = {
|
|
81
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
82
|
+
title: "Syncpoint Config",
|
|
83
|
+
description: "Configuration for syncpoint backup tool",
|
|
84
|
+
type: "object",
|
|
85
|
+
required: [
|
|
86
|
+
"backup"
|
|
87
|
+
],
|
|
88
|
+
properties: {
|
|
89
|
+
backup: {
|
|
90
|
+
type: "object",
|
|
91
|
+
description: "Backup configuration",
|
|
92
|
+
required: [
|
|
93
|
+
"targets",
|
|
94
|
+
"exclude",
|
|
95
|
+
"filename"
|
|
96
|
+
],
|
|
97
|
+
properties: {
|
|
98
|
+
targets: {
|
|
99
|
+
type: "array",
|
|
100
|
+
description: "List of files/directories to backup. Supports literal paths (e.g. ~/.zshrc), glob patterns (e.g. ~/.config/*.conf), and regex patterns (e.g. /\\.conf$/).",
|
|
101
|
+
items: {
|
|
102
|
+
type: "string",
|
|
103
|
+
validPattern: true
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
exclude: {
|
|
107
|
+
type: "array",
|
|
108
|
+
description: "List of patterns to exclude from backup. Supports glob (e.g. **/*.swp) and regex (e.g. /\\.bak$/) patterns.",
|
|
109
|
+
items: {
|
|
110
|
+
type: "string",
|
|
111
|
+
validPattern: true
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
filename: {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "Backup archive filename pattern. Available variables: {hostname}, {datetime}.",
|
|
117
|
+
minLength: 1
|
|
118
|
+
},
|
|
119
|
+
destination: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "Backup archive destination path. Default: ~/.syncpoint/backups/"
|
|
122
|
+
},
|
|
123
|
+
includeSensitiveFiles: {
|
|
124
|
+
type: "boolean",
|
|
125
|
+
description: "Include sensitive files (SSH keys, certificates, etc.) in backup. When false (default), files matching sensitive patterns (id_rsa, id_ed25519, *.pem, *.key) are automatically excluded."
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
additionalProperties: false
|
|
129
|
+
},
|
|
130
|
+
scripts: {
|
|
131
|
+
type: "object",
|
|
132
|
+
description: "Scripts configuration",
|
|
133
|
+
properties: {
|
|
134
|
+
includeInBackup: {
|
|
135
|
+
type: "boolean",
|
|
136
|
+
description: "Whether to include scripts/ directory in backup. Default: true."
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
additionalProperties: false
|
|
140
|
+
},
|
|
141
|
+
"yaml-language-server": {
|
|
142
|
+
type: "string",
|
|
143
|
+
description: "Editor directive for schema association; ignored at runtime."
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
additionalProperties: false
|
|
147
|
+
};
|
|
148
|
+
|
|
79
149
|
// src/schemas/ajv.ts
|
|
80
150
|
import Ajv from "ajv";
|
|
81
151
|
import addFormats from "ajv-formats";
|
|
@@ -181,45 +251,7 @@ ajv.addKeyword({
|
|
|
181
251
|
});
|
|
182
252
|
|
|
183
253
|
// src/schemas/config.schema.ts
|
|
184
|
-
var
|
|
185
|
-
type: "object",
|
|
186
|
-
required: ["backup"],
|
|
187
|
-
properties: {
|
|
188
|
-
backup: {
|
|
189
|
-
type: "object",
|
|
190
|
-
required: ["targets", "exclude", "filename"],
|
|
191
|
-
properties: {
|
|
192
|
-
targets: {
|
|
193
|
-
type: "array",
|
|
194
|
-
items: { type: "string", validPattern: true }
|
|
195
|
-
},
|
|
196
|
-
exclude: {
|
|
197
|
-
type: "array",
|
|
198
|
-
items: { type: "string", validPattern: true }
|
|
199
|
-
},
|
|
200
|
-
filename: {
|
|
201
|
-
type: "string",
|
|
202
|
-
minLength: 1
|
|
203
|
-
},
|
|
204
|
-
destination: {
|
|
205
|
-
type: "string"
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
additionalProperties: false
|
|
209
|
-
},
|
|
210
|
-
scripts: {
|
|
211
|
-
type: "object",
|
|
212
|
-
properties: {
|
|
213
|
-
includeInBackup: {
|
|
214
|
-
type: "boolean"
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
additionalProperties: false
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
additionalProperties: false
|
|
221
|
-
};
|
|
222
|
-
var validate2 = ajv.compile(configSchema);
|
|
254
|
+
var validate2 = ajv.compile(config_schema_default);
|
|
223
255
|
function validateConfig(data) {
|
|
224
256
|
const valid = validate2(data);
|
|
225
257
|
if (valid) return { valid: true };
|
|
@@ -435,8 +467,11 @@ var logger = {
|
|
|
435
467
|
import { createHash } from "crypto";
|
|
436
468
|
import { lstat, readFile as readFile2, readlink } from "fs/promises";
|
|
437
469
|
|
|
438
|
-
//
|
|
439
|
-
var
|
|
470
|
+
// assets/schemas/metadata.schema.json
|
|
471
|
+
var metadata_schema_default = {
|
|
472
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
473
|
+
title: "Syncpoint Backup Metadata",
|
|
474
|
+
description: "Metadata stored inside backup archives as _metadata.json",
|
|
440
475
|
type: "object",
|
|
441
476
|
required: [
|
|
442
477
|
"version",
|
|
@@ -449,57 +484,114 @@ var metadataSchema = {
|
|
|
449
484
|
"summary"
|
|
450
485
|
],
|
|
451
486
|
properties: {
|
|
452
|
-
version: {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
487
|
+
version: {
|
|
488
|
+
type: "string",
|
|
489
|
+
description: "Metadata schema version."
|
|
490
|
+
},
|
|
491
|
+
toolVersion: {
|
|
492
|
+
type: "string",
|
|
493
|
+
description: "Syncpoint tool version used to create the backup."
|
|
494
|
+
},
|
|
495
|
+
createdAt: {
|
|
496
|
+
type: "string",
|
|
497
|
+
description: "ISO 8601 timestamp of backup creation."
|
|
498
|
+
},
|
|
499
|
+
hostname: {
|
|
500
|
+
type: "string",
|
|
501
|
+
description: "Hostname of the machine where the backup was created."
|
|
502
|
+
},
|
|
456
503
|
system: {
|
|
457
504
|
type: "object",
|
|
505
|
+
description: "System information at backup time.",
|
|
458
506
|
required: ["platform", "release", "arch"],
|
|
459
507
|
properties: {
|
|
460
|
-
platform: {
|
|
461
|
-
|
|
462
|
-
|
|
508
|
+
platform: {
|
|
509
|
+
type: "string",
|
|
510
|
+
description: "Operating system platform (e.g. darwin, linux)."
|
|
511
|
+
},
|
|
512
|
+
release: {
|
|
513
|
+
type: "string",
|
|
514
|
+
description: "OS kernel release version."
|
|
515
|
+
},
|
|
516
|
+
arch: {
|
|
517
|
+
type: "string",
|
|
518
|
+
description: "CPU architecture (e.g. arm64, x64)."
|
|
519
|
+
}
|
|
463
520
|
},
|
|
464
521
|
additionalProperties: false
|
|
465
522
|
},
|
|
466
523
|
config: {
|
|
467
524
|
type: "object",
|
|
525
|
+
description: "Backup configuration snapshot.",
|
|
468
526
|
required: ["filename"],
|
|
469
527
|
properties: {
|
|
470
|
-
filename: {
|
|
471
|
-
|
|
528
|
+
filename: {
|
|
529
|
+
type: "string",
|
|
530
|
+
description: "Filename pattern used for the backup."
|
|
531
|
+
},
|
|
532
|
+
destination: {
|
|
533
|
+
type: "string",
|
|
534
|
+
description: "Custom destination path, if configured."
|
|
535
|
+
}
|
|
472
536
|
},
|
|
473
537
|
additionalProperties: false
|
|
474
538
|
},
|
|
475
539
|
files: {
|
|
476
540
|
type: "array",
|
|
541
|
+
description: "List of files included in the backup.",
|
|
477
542
|
items: {
|
|
478
543
|
type: "object",
|
|
479
544
|
required: ["path", "absolutePath", "size", "hash"],
|
|
480
545
|
properties: {
|
|
481
|
-
path: {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
546
|
+
path: {
|
|
547
|
+
type: "string",
|
|
548
|
+
description: "Display path (e.g. ~/.zshrc)."
|
|
549
|
+
},
|
|
550
|
+
absolutePath: {
|
|
551
|
+
type: "string",
|
|
552
|
+
description: "Full filesystem path."
|
|
553
|
+
},
|
|
554
|
+
size: {
|
|
555
|
+
type: "number",
|
|
556
|
+
description: "File size in bytes.",
|
|
557
|
+
minimum: 0
|
|
558
|
+
},
|
|
559
|
+
hash: {
|
|
560
|
+
type: "string",
|
|
561
|
+
description: "SHA-256 hash of file contents."
|
|
562
|
+
},
|
|
563
|
+
type: {
|
|
564
|
+
type: "string",
|
|
565
|
+
description: "File type (e.g. symlink, directory)."
|
|
566
|
+
}
|
|
486
567
|
},
|
|
487
568
|
additionalProperties: false
|
|
488
569
|
}
|
|
489
570
|
},
|
|
490
571
|
summary: {
|
|
491
572
|
type: "object",
|
|
573
|
+
description: "Backup summary statistics.",
|
|
492
574
|
required: ["fileCount", "totalSize"],
|
|
493
575
|
properties: {
|
|
494
|
-
fileCount: {
|
|
495
|
-
|
|
576
|
+
fileCount: {
|
|
577
|
+
type: "integer",
|
|
578
|
+
description: "Total number of files in the backup.",
|
|
579
|
+
minimum: 0
|
|
580
|
+
},
|
|
581
|
+
totalSize: {
|
|
582
|
+
type: "number",
|
|
583
|
+
description: "Total size of all files in bytes.",
|
|
584
|
+
minimum: 0
|
|
585
|
+
}
|
|
496
586
|
},
|
|
497
587
|
additionalProperties: false
|
|
498
588
|
}
|
|
499
589
|
},
|
|
500
590
|
additionalProperties: false
|
|
501
591
|
};
|
|
502
|
-
|
|
592
|
+
|
|
593
|
+
// src/schemas/metadata.schema.ts
|
|
594
|
+
var validate3 = ajv.compile(metadata_schema_default);
|
|
503
595
|
function validateMetadata(data) {
|
|
504
596
|
const valid = validate3(data);
|
|
505
597
|
if (valid) return { valid: true };
|
|
@@ -510,7 +602,7 @@ function validateMetadata(data) {
|
|
|
510
602
|
}
|
|
511
603
|
|
|
512
604
|
// src/version.ts
|
|
513
|
-
var VERSION = "0.0.
|
|
605
|
+
var VERSION = "0.0.5";
|
|
514
606
|
|
|
515
607
|
// src/core/metadata.ts
|
|
516
608
|
var METADATA_VERSION = "1.0.0";
|
|
@@ -695,6 +787,10 @@ async function scanTargets(config) {
|
|
|
695
787
|
});
|
|
696
788
|
for (const match of allFiles) {
|
|
697
789
|
if (regex.test(match) && !isExcluded(match)) {
|
|
790
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(match)) {
|
|
791
|
+
logger.warn(`Sensitive file excluded: ${match}`);
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
698
794
|
const entry = await collectFileInfo(match, match);
|
|
699
795
|
found.push(entry);
|
|
700
796
|
}
|
|
@@ -723,6 +819,10 @@ async function scanTargets(config) {
|
|
|
723
819
|
});
|
|
724
820
|
for (const match of matches) {
|
|
725
821
|
if (!isExcluded(match)) {
|
|
822
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(match)) {
|
|
823
|
+
logger.warn(`Sensitive file excluded: ${match}`);
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
726
826
|
const entry = await collectFileInfo(match, match);
|
|
727
827
|
found.push(entry);
|
|
728
828
|
}
|
|
@@ -756,6 +856,10 @@ async function scanTargets(config) {
|
|
|
756
856
|
});
|
|
757
857
|
for (const match of matches) {
|
|
758
858
|
if (!isExcluded(match)) {
|
|
859
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(match)) {
|
|
860
|
+
logger.warn(`Sensitive file excluded: ${match}`);
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
759
863
|
const entry = await collectFileInfo(match, match);
|
|
760
864
|
found.push(entry);
|
|
761
865
|
}
|
|
@@ -767,15 +871,16 @@ async function scanTargets(config) {
|
|
|
767
871
|
if (isExcluded(absPath)) {
|
|
768
872
|
continue;
|
|
769
873
|
}
|
|
874
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(absPath)) {
|
|
875
|
+
logger.warn(`Sensitive file excluded: ${target}`);
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
770
878
|
const entry = await collectFileInfo(absPath, absPath);
|
|
771
879
|
if (entry.size > LARGE_FILE_THRESHOLD) {
|
|
772
880
|
logger.warn(
|
|
773
881
|
`Large file (>${Math.round(LARGE_FILE_THRESHOLD / 1024 / 1024)}MB): ${target}`
|
|
774
882
|
);
|
|
775
883
|
}
|
|
776
|
-
if (isSensitiveFile(absPath)) {
|
|
777
|
-
logger.warn(`Sensitive file detected: ${target}`);
|
|
778
|
-
}
|
|
779
884
|
found.push(entry);
|
|
780
885
|
}
|
|
781
886
|
}
|
|
@@ -1007,27 +1112,61 @@ import { readFile as readFile4, readdir as readdir3 } from "fs/promises";
|
|
|
1007
1112
|
import { join as join9 } from "path";
|
|
1008
1113
|
import YAML2 from "yaml";
|
|
1009
1114
|
|
|
1010
|
-
//
|
|
1011
|
-
var
|
|
1115
|
+
// assets/schemas/template.schema.json
|
|
1116
|
+
var template_schema_default = {
|
|
1117
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
1118
|
+
title: "Syncpoint Template",
|
|
1119
|
+
description: "Provisioning template for syncpoint",
|
|
1012
1120
|
type: "object",
|
|
1013
1121
|
required: ["name", "steps"],
|
|
1014
1122
|
properties: {
|
|
1015
|
-
name: {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1123
|
+
name: {
|
|
1124
|
+
type: "string",
|
|
1125
|
+
description: "Template name.",
|
|
1126
|
+
minLength: 1
|
|
1127
|
+
},
|
|
1128
|
+
description: {
|
|
1129
|
+
type: "string",
|
|
1130
|
+
description: "Template description."
|
|
1131
|
+
},
|
|
1132
|
+
backup: {
|
|
1133
|
+
type: "string",
|
|
1134
|
+
description: "Backup name to restore automatically after provisioning."
|
|
1135
|
+
},
|
|
1136
|
+
sudo: {
|
|
1137
|
+
type: "boolean",
|
|
1138
|
+
description: "Whether sudo privilege is required. If true, requests sudo authentication before execution."
|
|
1139
|
+
},
|
|
1019
1140
|
steps: {
|
|
1020
1141
|
type: "array",
|
|
1142
|
+
description: "List of provisioning steps. At least 1 step required.",
|
|
1021
1143
|
minItems: 1,
|
|
1022
1144
|
items: {
|
|
1023
1145
|
type: "object",
|
|
1024
1146
|
required: ["name", "command"],
|
|
1025
1147
|
properties: {
|
|
1026
|
-
name: {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1148
|
+
name: {
|
|
1149
|
+
type: "string",
|
|
1150
|
+
description: "Step name.",
|
|
1151
|
+
minLength: 1
|
|
1152
|
+
},
|
|
1153
|
+
description: {
|
|
1154
|
+
type: "string",
|
|
1155
|
+
description: "Step description."
|
|
1156
|
+
},
|
|
1157
|
+
command: {
|
|
1158
|
+
type: "string",
|
|
1159
|
+
description: "Shell command to execute.",
|
|
1160
|
+
minLength: 1
|
|
1161
|
+
},
|
|
1162
|
+
skip_if: {
|
|
1163
|
+
type: "string",
|
|
1164
|
+
description: "Skip this step if this command exits with code 0."
|
|
1165
|
+
},
|
|
1166
|
+
continue_on_error: {
|
|
1167
|
+
type: "boolean",
|
|
1168
|
+
description: "Continue to next step even if this fails. Default: false."
|
|
1169
|
+
}
|
|
1031
1170
|
},
|
|
1032
1171
|
additionalProperties: false
|
|
1033
1172
|
}
|
|
@@ -1035,7 +1174,9 @@ var templateSchema = {
|
|
|
1035
1174
|
},
|
|
1036
1175
|
additionalProperties: false
|
|
1037
1176
|
};
|
|
1038
|
-
|
|
1177
|
+
|
|
1178
|
+
// src/schemas/template.schema.ts
|
|
1179
|
+
var validate4 = ajv.compile(template_schema_default);
|
|
1039
1180
|
function validateTemplate(data) {
|
|
1040
1181
|
const valid = validate4(data);
|
|
1041
1182
|
if (valid) return { valid: true };
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export interface SyncpointConfig {
|
|
2
|
+
/** Editor directive for schema association; ignored at runtime. */
|
|
3
|
+
'yaml-language-server'?: string;
|
|
2
4
|
backup: {
|
|
3
5
|
targets: string[];
|
|
4
6
|
exclude: string[];
|
|
5
7
|
filename: string;
|
|
6
8
|
destination?: string;
|
|
9
|
+
includeSensitiveFiles?: boolean;
|
|
7
10
|
};
|
|
8
11
|
scripts: {
|
|
9
12
|
includeInBackup: boolean;
|
|
@@ -81,6 +84,13 @@ export interface StepResult {
|
|
|
81
84
|
error?: string;
|
|
82
85
|
output?: string;
|
|
83
86
|
}
|
|
87
|
+
export interface MigrateResult {
|
|
88
|
+
added: string[];
|
|
89
|
+
deprecated: string[];
|
|
90
|
+
preserved: string[];
|
|
91
|
+
backupPath: string;
|
|
92
|
+
migrated: boolean;
|
|
93
|
+
}
|
|
84
94
|
export interface BackupOptions {
|
|
85
95
|
dryRun?: boolean;
|
|
86
96
|
tag?: string;
|
package/dist/version.d.ts
CHANGED