@lumy-pack/syncpoint 0.0.4 → 0.0.6
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 +8 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MigrateResult } from '../utils/types.js';
|
|
2
|
+
export interface DiffResult {
|
|
3
|
+
added: string[][];
|
|
4
|
+
removed: string[][];
|
|
5
|
+
existing: string[][];
|
|
6
|
+
}
|
|
7
|
+
export declare function diffConfigFields(userData: unknown): DiffResult;
|
|
8
|
+
export declare function buildMigratedDocument(templateText: string, userData: unknown, diff: DiffResult): string;
|
|
9
|
+
export declare function migrateConfig(options?: {
|
|
10
|
+
dryRun?: boolean;
|
|
11
|
+
}): Promise<MigrateResult>;
|
package/dist/index.cjs
CHANGED
|
@@ -126,6 +126,76 @@ function getSubDir(sub) {
|
|
|
126
126
|
return (0, import_node_path2.join)(getAppDir(), sub);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
// assets/schemas/config.schema.json
|
|
130
|
+
var config_schema_default = {
|
|
131
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
132
|
+
title: "Syncpoint Config",
|
|
133
|
+
description: "Configuration for syncpoint backup tool",
|
|
134
|
+
type: "object",
|
|
135
|
+
required: [
|
|
136
|
+
"backup"
|
|
137
|
+
],
|
|
138
|
+
properties: {
|
|
139
|
+
backup: {
|
|
140
|
+
type: "object",
|
|
141
|
+
description: "Backup configuration",
|
|
142
|
+
required: [
|
|
143
|
+
"targets",
|
|
144
|
+
"exclude",
|
|
145
|
+
"filename"
|
|
146
|
+
],
|
|
147
|
+
properties: {
|
|
148
|
+
targets: {
|
|
149
|
+
type: "array",
|
|
150
|
+
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$/).",
|
|
151
|
+
items: {
|
|
152
|
+
type: "string",
|
|
153
|
+
validPattern: true
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
exclude: {
|
|
157
|
+
type: "array",
|
|
158
|
+
description: "List of patterns to exclude from backup. Supports glob (e.g. **/*.swp) and regex (e.g. /\\.bak$/) patterns.",
|
|
159
|
+
items: {
|
|
160
|
+
type: "string",
|
|
161
|
+
validPattern: true
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
filename: {
|
|
165
|
+
type: "string",
|
|
166
|
+
description: "Backup archive filename pattern. Available variables: {hostname}, {datetime}.",
|
|
167
|
+
minLength: 1
|
|
168
|
+
},
|
|
169
|
+
destination: {
|
|
170
|
+
type: "string",
|
|
171
|
+
description: "Backup archive destination path. Default: ~/.syncpoint/backups/"
|
|
172
|
+
},
|
|
173
|
+
includeSensitiveFiles: {
|
|
174
|
+
type: "boolean",
|
|
175
|
+
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."
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
additionalProperties: false
|
|
179
|
+
},
|
|
180
|
+
scripts: {
|
|
181
|
+
type: "object",
|
|
182
|
+
description: "Scripts configuration",
|
|
183
|
+
properties: {
|
|
184
|
+
includeInBackup: {
|
|
185
|
+
type: "boolean",
|
|
186
|
+
description: "Whether to include scripts/ directory in backup. Default: true."
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
additionalProperties: false
|
|
190
|
+
},
|
|
191
|
+
"yaml-language-server": {
|
|
192
|
+
type: "string",
|
|
193
|
+
description: "Editor directive for schema association; ignored at runtime."
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
additionalProperties: false
|
|
197
|
+
};
|
|
198
|
+
|
|
129
199
|
// src/schemas/ajv.ts
|
|
130
200
|
var import_ajv = __toESM(require("ajv"), 1);
|
|
131
201
|
var import_ajv_formats = __toESM(require("ajv-formats"), 1);
|
|
@@ -231,45 +301,7 @@ ajv.addKeyword({
|
|
|
231
301
|
});
|
|
232
302
|
|
|
233
303
|
// src/schemas/config.schema.ts
|
|
234
|
-
var
|
|
235
|
-
type: "object",
|
|
236
|
-
required: ["backup"],
|
|
237
|
-
properties: {
|
|
238
|
-
backup: {
|
|
239
|
-
type: "object",
|
|
240
|
-
required: ["targets", "exclude", "filename"],
|
|
241
|
-
properties: {
|
|
242
|
-
targets: {
|
|
243
|
-
type: "array",
|
|
244
|
-
items: { type: "string", validPattern: true }
|
|
245
|
-
},
|
|
246
|
-
exclude: {
|
|
247
|
-
type: "array",
|
|
248
|
-
items: { type: "string", validPattern: true }
|
|
249
|
-
},
|
|
250
|
-
filename: {
|
|
251
|
-
type: "string",
|
|
252
|
-
minLength: 1
|
|
253
|
-
},
|
|
254
|
-
destination: {
|
|
255
|
-
type: "string"
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
additionalProperties: false
|
|
259
|
-
},
|
|
260
|
-
scripts: {
|
|
261
|
-
type: "object",
|
|
262
|
-
properties: {
|
|
263
|
-
includeInBackup: {
|
|
264
|
-
type: "boolean"
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
additionalProperties: false
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
additionalProperties: false
|
|
271
|
-
};
|
|
272
|
-
var validate2 = ajv.compile(configSchema);
|
|
304
|
+
var validate2 = ajv.compile(config_schema_default);
|
|
273
305
|
function validateConfig(data) {
|
|
274
306
|
const valid = validate2(data);
|
|
275
307
|
if (valid) return { valid: true };
|
|
@@ -485,8 +517,11 @@ var logger = {
|
|
|
485
517
|
var import_node_crypto = require("crypto");
|
|
486
518
|
var import_promises4 = require("fs/promises");
|
|
487
519
|
|
|
488
|
-
//
|
|
489
|
-
var
|
|
520
|
+
// assets/schemas/metadata.schema.json
|
|
521
|
+
var metadata_schema_default = {
|
|
522
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
523
|
+
title: "Syncpoint Backup Metadata",
|
|
524
|
+
description: "Metadata stored inside backup archives as _metadata.json",
|
|
490
525
|
type: "object",
|
|
491
526
|
required: [
|
|
492
527
|
"version",
|
|
@@ -499,57 +534,114 @@ var metadataSchema = {
|
|
|
499
534
|
"summary"
|
|
500
535
|
],
|
|
501
536
|
properties: {
|
|
502
|
-
version: {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
537
|
+
version: {
|
|
538
|
+
type: "string",
|
|
539
|
+
description: "Metadata schema version."
|
|
540
|
+
},
|
|
541
|
+
toolVersion: {
|
|
542
|
+
type: "string",
|
|
543
|
+
description: "Syncpoint tool version used to create the backup."
|
|
544
|
+
},
|
|
545
|
+
createdAt: {
|
|
546
|
+
type: "string",
|
|
547
|
+
description: "ISO 8601 timestamp of backup creation."
|
|
548
|
+
},
|
|
549
|
+
hostname: {
|
|
550
|
+
type: "string",
|
|
551
|
+
description: "Hostname of the machine where the backup was created."
|
|
552
|
+
},
|
|
506
553
|
system: {
|
|
507
554
|
type: "object",
|
|
555
|
+
description: "System information at backup time.",
|
|
508
556
|
required: ["platform", "release", "arch"],
|
|
509
557
|
properties: {
|
|
510
|
-
platform: {
|
|
511
|
-
|
|
512
|
-
|
|
558
|
+
platform: {
|
|
559
|
+
type: "string",
|
|
560
|
+
description: "Operating system platform (e.g. darwin, linux)."
|
|
561
|
+
},
|
|
562
|
+
release: {
|
|
563
|
+
type: "string",
|
|
564
|
+
description: "OS kernel release version."
|
|
565
|
+
},
|
|
566
|
+
arch: {
|
|
567
|
+
type: "string",
|
|
568
|
+
description: "CPU architecture (e.g. arm64, x64)."
|
|
569
|
+
}
|
|
513
570
|
},
|
|
514
571
|
additionalProperties: false
|
|
515
572
|
},
|
|
516
573
|
config: {
|
|
517
574
|
type: "object",
|
|
575
|
+
description: "Backup configuration snapshot.",
|
|
518
576
|
required: ["filename"],
|
|
519
577
|
properties: {
|
|
520
|
-
filename: {
|
|
521
|
-
|
|
578
|
+
filename: {
|
|
579
|
+
type: "string",
|
|
580
|
+
description: "Filename pattern used for the backup."
|
|
581
|
+
},
|
|
582
|
+
destination: {
|
|
583
|
+
type: "string",
|
|
584
|
+
description: "Custom destination path, if configured."
|
|
585
|
+
}
|
|
522
586
|
},
|
|
523
587
|
additionalProperties: false
|
|
524
588
|
},
|
|
525
589
|
files: {
|
|
526
590
|
type: "array",
|
|
591
|
+
description: "List of files included in the backup.",
|
|
527
592
|
items: {
|
|
528
593
|
type: "object",
|
|
529
594
|
required: ["path", "absolutePath", "size", "hash"],
|
|
530
595
|
properties: {
|
|
531
|
-
path: {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
596
|
+
path: {
|
|
597
|
+
type: "string",
|
|
598
|
+
description: "Display path (e.g. ~/.zshrc)."
|
|
599
|
+
},
|
|
600
|
+
absolutePath: {
|
|
601
|
+
type: "string",
|
|
602
|
+
description: "Full filesystem path."
|
|
603
|
+
},
|
|
604
|
+
size: {
|
|
605
|
+
type: "number",
|
|
606
|
+
description: "File size in bytes.",
|
|
607
|
+
minimum: 0
|
|
608
|
+
},
|
|
609
|
+
hash: {
|
|
610
|
+
type: "string",
|
|
611
|
+
description: "SHA-256 hash of file contents."
|
|
612
|
+
},
|
|
613
|
+
type: {
|
|
614
|
+
type: "string",
|
|
615
|
+
description: "File type (e.g. symlink, directory)."
|
|
616
|
+
}
|
|
536
617
|
},
|
|
537
618
|
additionalProperties: false
|
|
538
619
|
}
|
|
539
620
|
},
|
|
540
621
|
summary: {
|
|
541
622
|
type: "object",
|
|
623
|
+
description: "Backup summary statistics.",
|
|
542
624
|
required: ["fileCount", "totalSize"],
|
|
543
625
|
properties: {
|
|
544
|
-
fileCount: {
|
|
545
|
-
|
|
626
|
+
fileCount: {
|
|
627
|
+
type: "integer",
|
|
628
|
+
description: "Total number of files in the backup.",
|
|
629
|
+
minimum: 0
|
|
630
|
+
},
|
|
631
|
+
totalSize: {
|
|
632
|
+
type: "number",
|
|
633
|
+
description: "Total size of all files in bytes.",
|
|
634
|
+
minimum: 0
|
|
635
|
+
}
|
|
546
636
|
},
|
|
547
637
|
additionalProperties: false
|
|
548
638
|
}
|
|
549
639
|
},
|
|
550
640
|
additionalProperties: false
|
|
551
641
|
};
|
|
552
|
-
|
|
642
|
+
|
|
643
|
+
// src/schemas/metadata.schema.ts
|
|
644
|
+
var validate3 = ajv.compile(metadata_schema_default);
|
|
553
645
|
function validateMetadata(data) {
|
|
554
646
|
const valid = validate3(data);
|
|
555
647
|
if (valid) return { valid: true };
|
|
@@ -560,7 +652,7 @@ function validateMetadata(data) {
|
|
|
560
652
|
}
|
|
561
653
|
|
|
562
654
|
// src/version.ts
|
|
563
|
-
var VERSION = "0.0.
|
|
655
|
+
var VERSION = "0.0.6";
|
|
564
656
|
|
|
565
657
|
// src/core/metadata.ts
|
|
566
658
|
var METADATA_VERSION = "1.0.0";
|
|
@@ -745,6 +837,10 @@ async function scanTargets(config) {
|
|
|
745
837
|
});
|
|
746
838
|
for (const match of allFiles) {
|
|
747
839
|
if (regex.test(match) && !isExcluded(match)) {
|
|
840
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(match)) {
|
|
841
|
+
logger.warn(`Sensitive file excluded: ${match}`);
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
748
844
|
const entry = await collectFileInfo(match, match);
|
|
749
845
|
found.push(entry);
|
|
750
846
|
}
|
|
@@ -773,6 +869,10 @@ async function scanTargets(config) {
|
|
|
773
869
|
});
|
|
774
870
|
for (const match of matches) {
|
|
775
871
|
if (!isExcluded(match)) {
|
|
872
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(match)) {
|
|
873
|
+
logger.warn(`Sensitive file excluded: ${match}`);
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
776
876
|
const entry = await collectFileInfo(match, match);
|
|
777
877
|
found.push(entry);
|
|
778
878
|
}
|
|
@@ -806,6 +906,10 @@ async function scanTargets(config) {
|
|
|
806
906
|
});
|
|
807
907
|
for (const match of matches) {
|
|
808
908
|
if (!isExcluded(match)) {
|
|
909
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(match)) {
|
|
910
|
+
logger.warn(`Sensitive file excluded: ${match}`);
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
809
913
|
const entry = await collectFileInfo(match, match);
|
|
810
914
|
found.push(entry);
|
|
811
915
|
}
|
|
@@ -817,15 +921,16 @@ async function scanTargets(config) {
|
|
|
817
921
|
if (isExcluded(absPath)) {
|
|
818
922
|
continue;
|
|
819
923
|
}
|
|
924
|
+
if (!config.backup.includeSensitiveFiles && isSensitiveFile(absPath)) {
|
|
925
|
+
logger.warn(`Sensitive file excluded: ${target}`);
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
820
928
|
const entry = await collectFileInfo(absPath, absPath);
|
|
821
929
|
if (entry.size > LARGE_FILE_THRESHOLD) {
|
|
822
930
|
logger.warn(
|
|
823
931
|
`Large file (>${Math.round(LARGE_FILE_THRESHOLD / 1024 / 1024)}MB): ${target}`
|
|
824
932
|
);
|
|
825
933
|
}
|
|
826
|
-
if (isSensitiveFile(absPath)) {
|
|
827
|
-
logger.warn(`Sensitive file detected: ${target}`);
|
|
828
|
-
}
|
|
829
934
|
found.push(entry);
|
|
830
935
|
}
|
|
831
936
|
}
|
|
@@ -1057,27 +1162,61 @@ var import_promises8 = require("fs/promises");
|
|
|
1057
1162
|
var import_node_path9 = require("path");
|
|
1058
1163
|
var import_yaml2 = __toESM(require("yaml"), 1);
|
|
1059
1164
|
|
|
1060
|
-
//
|
|
1061
|
-
var
|
|
1165
|
+
// assets/schemas/template.schema.json
|
|
1166
|
+
var template_schema_default = {
|
|
1167
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
1168
|
+
title: "Syncpoint Template",
|
|
1169
|
+
description: "Provisioning template for syncpoint",
|
|
1062
1170
|
type: "object",
|
|
1063
1171
|
required: ["name", "steps"],
|
|
1064
1172
|
properties: {
|
|
1065
|
-
name: {
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1173
|
+
name: {
|
|
1174
|
+
type: "string",
|
|
1175
|
+
description: "Template name.",
|
|
1176
|
+
minLength: 1
|
|
1177
|
+
},
|
|
1178
|
+
description: {
|
|
1179
|
+
type: "string",
|
|
1180
|
+
description: "Template description."
|
|
1181
|
+
},
|
|
1182
|
+
backup: {
|
|
1183
|
+
type: "string",
|
|
1184
|
+
description: "Backup name to restore automatically after provisioning."
|
|
1185
|
+
},
|
|
1186
|
+
sudo: {
|
|
1187
|
+
type: "boolean",
|
|
1188
|
+
description: "Whether sudo privilege is required. If true, requests sudo authentication before execution."
|
|
1189
|
+
},
|
|
1069
1190
|
steps: {
|
|
1070
1191
|
type: "array",
|
|
1192
|
+
description: "List of provisioning steps. At least 1 step required.",
|
|
1071
1193
|
minItems: 1,
|
|
1072
1194
|
items: {
|
|
1073
1195
|
type: "object",
|
|
1074
1196
|
required: ["name", "command"],
|
|
1075
1197
|
properties: {
|
|
1076
|
-
name: {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1198
|
+
name: {
|
|
1199
|
+
type: "string",
|
|
1200
|
+
description: "Step name.",
|
|
1201
|
+
minLength: 1
|
|
1202
|
+
},
|
|
1203
|
+
description: {
|
|
1204
|
+
type: "string",
|
|
1205
|
+
description: "Step description."
|
|
1206
|
+
},
|
|
1207
|
+
command: {
|
|
1208
|
+
type: "string",
|
|
1209
|
+
description: "Shell command to execute.",
|
|
1210
|
+
minLength: 1
|
|
1211
|
+
},
|
|
1212
|
+
skip_if: {
|
|
1213
|
+
type: "string",
|
|
1214
|
+
description: "Skip this step if this command exits with code 0."
|
|
1215
|
+
},
|
|
1216
|
+
continue_on_error: {
|
|
1217
|
+
type: "boolean",
|
|
1218
|
+
description: "Continue to next step even if this fails. Default: false."
|
|
1219
|
+
}
|
|
1081
1220
|
},
|
|
1082
1221
|
additionalProperties: false
|
|
1083
1222
|
}
|
|
@@ -1085,7 +1224,9 @@ var templateSchema = {
|
|
|
1085
1224
|
},
|
|
1086
1225
|
additionalProperties: false
|
|
1087
1226
|
};
|
|
1088
|
-
|
|
1227
|
+
|
|
1228
|
+
// src/schemas/template.schema.ts
|
|
1229
|
+
var validate4 = ajv.compile(template_schema_default);
|
|
1089
1230
|
function validateTemplate(data) {
|
|
1090
1231
|
const valid = validate4(data);
|
|
1091
1232
|
if (valid) return { valid: true };
|