@lumy-pack/syncpoint 0.0.9 → 0.0.10
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/dist/cli.mjs +497 -76
- package/dist/errors.d.ts +16 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/utils/command-registry.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,8 +1,124 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/utils/assets.ts
|
|
13
|
+
var assets_exports = {};
|
|
14
|
+
__export(assets_exports, {
|
|
15
|
+
getAssetPath: () => getAssetPath,
|
|
16
|
+
readAsset: () => readAsset
|
|
17
|
+
});
|
|
18
|
+
import { existsSync, readFileSync } from "fs";
|
|
19
|
+
import { dirname, join as join6 } from "path";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
21
|
+
function getPackageRoot() {
|
|
22
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
while (dir !== dirname(dir)) {
|
|
24
|
+
if (existsSync(join6(dir, "package.json"))) return dir;
|
|
25
|
+
dir = dirname(dir);
|
|
26
|
+
}
|
|
27
|
+
throw new Error("Could not find package root");
|
|
28
|
+
}
|
|
29
|
+
function getAssetPath(filename) {
|
|
30
|
+
return join6(getPackageRoot(), "assets", filename);
|
|
31
|
+
}
|
|
32
|
+
function readAsset(filename) {
|
|
33
|
+
return readFileSync(getAssetPath(filename), "utf-8");
|
|
34
|
+
}
|
|
35
|
+
var init_assets = __esm({
|
|
36
|
+
"src/utils/assets.ts"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// src/prompts/wizard-template.ts
|
|
42
|
+
var wizard_template_exports = {};
|
|
43
|
+
__export(wizard_template_exports, {
|
|
44
|
+
generateTemplateWizardPrompt: () => generateTemplateWizardPrompt
|
|
45
|
+
});
|
|
46
|
+
function generateTemplateWizardPrompt(variables) {
|
|
47
|
+
return `You are a Syncpoint provisioning template assistant. Your role is to help users create automated environment setup templates.
|
|
48
|
+
|
|
49
|
+
**Input:**
|
|
50
|
+
1. User's provisioning requirements (described in natural language)
|
|
51
|
+
2. Example template structure (YAML)
|
|
52
|
+
|
|
53
|
+
**Your Task:**
|
|
54
|
+
1. Ask clarifying questions to understand the provisioning workflow:
|
|
55
|
+
- What software/tools need to be installed?
|
|
56
|
+
- What dependencies should be checked?
|
|
57
|
+
- Are there any configuration steps after installation?
|
|
58
|
+
- Should any steps require sudo privileges?
|
|
59
|
+
- Should any steps be conditional (skip_if)?
|
|
60
|
+
2. Based on user responses, generate a complete provision template
|
|
61
|
+
|
|
62
|
+
**Output Requirements:**
|
|
63
|
+
- Pure YAML format only (no markdown, no code blocks, no explanations)
|
|
64
|
+
- Must be valid according to Syncpoint template schema
|
|
65
|
+
- Required fields:
|
|
66
|
+
- \`name\`: Template name
|
|
67
|
+
- \`steps\`: Array of provisioning steps (minimum 1)
|
|
68
|
+
- Each step must include:
|
|
69
|
+
- \`name\`: Step name (required)
|
|
70
|
+
- \`command\`: Shell command to execute (required)
|
|
71
|
+
- \`description\`: Step description (optional)
|
|
72
|
+
- \`skip_if\`: Condition to skip step (optional)
|
|
73
|
+
- \`continue_on_error\`: Whether to continue on failure (optional, default: false)
|
|
74
|
+
- Optional template fields:
|
|
75
|
+
- \`description\`: Template description
|
|
76
|
+
- \`backup\`: Backup name to restore after provisioning
|
|
77
|
+
- \`sudo\`: Whether sudo is required (boolean)
|
|
78
|
+
|
|
79
|
+
**Example Template:**
|
|
80
|
+
${variables.exampleTemplate}
|
|
81
|
+
|
|
82
|
+
Begin by asking the user to describe their provisioning needs.`;
|
|
83
|
+
}
|
|
84
|
+
var init_wizard_template = __esm({
|
|
85
|
+
"src/prompts/wizard-template.ts"() {
|
|
86
|
+
"use strict";
|
|
87
|
+
}
|
|
88
|
+
});
|
|
2
89
|
|
|
3
90
|
// src/cli.ts
|
|
4
91
|
import { Command } from "commander";
|
|
5
92
|
|
|
93
|
+
// ../shared/src/respond.ts
|
|
94
|
+
function respond(command, data, startTime, version) {
|
|
95
|
+
const response = {
|
|
96
|
+
ok: true,
|
|
97
|
+
command,
|
|
98
|
+
data,
|
|
99
|
+
meta: {
|
|
100
|
+
version,
|
|
101
|
+
durationMs: Date.now() - startTime,
|
|
102
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
106
|
+
}
|
|
107
|
+
function respondError(command, code, message, startTime, version, details) {
|
|
108
|
+
const response = {
|
|
109
|
+
ok: false,
|
|
110
|
+
command,
|
|
111
|
+
error: { code, message, ...details !== void 0 ? { details } : {} },
|
|
112
|
+
meta: {
|
|
113
|
+
version,
|
|
114
|
+
durationMs: Date.now() - startTime,
|
|
115
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
119
|
+
process.exitCode = 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
6
122
|
// src/commands/Backup.tsx
|
|
7
123
|
import { Box, Static, Text as Text2, useApp } from "ink";
|
|
8
124
|
import { render } from "ink";
|
|
@@ -486,7 +602,7 @@ function validateMetadata(data) {
|
|
|
486
602
|
}
|
|
487
603
|
|
|
488
604
|
// src/version.ts
|
|
489
|
-
var VERSION = "0.0.
|
|
605
|
+
var VERSION = "0.0.10";
|
|
490
606
|
|
|
491
607
|
// src/core/metadata.ts
|
|
492
608
|
var METADATA_VERSION = "1.0.0";
|
|
@@ -912,26 +1028,8 @@ function validateConfig(data) {
|
|
|
912
1028
|
return { valid: false, errors };
|
|
913
1029
|
}
|
|
914
1030
|
|
|
915
|
-
// src/utils/assets.ts
|
|
916
|
-
import { existsSync, readFileSync } from "fs";
|
|
917
|
-
import { dirname, join as join6 } from "path";
|
|
918
|
-
import { fileURLToPath } from "url";
|
|
919
|
-
function getPackageRoot() {
|
|
920
|
-
let dir = dirname(fileURLToPath(import.meta.url));
|
|
921
|
-
while (dir !== dirname(dir)) {
|
|
922
|
-
if (existsSync(join6(dir, "package.json"))) return dir;
|
|
923
|
-
dir = dirname(dir);
|
|
924
|
-
}
|
|
925
|
-
throw new Error("Could not find package root");
|
|
926
|
-
}
|
|
927
|
-
function getAssetPath(filename) {
|
|
928
|
-
return join6(getPackageRoot(), "assets", filename);
|
|
929
|
-
}
|
|
930
|
-
function readAsset(filename) {
|
|
931
|
-
return readFileSync(getAssetPath(filename), "utf-8");
|
|
932
|
-
}
|
|
933
|
-
|
|
934
1031
|
// src/core/config.ts
|
|
1032
|
+
init_assets();
|
|
935
1033
|
function stripDangerousKeys(obj) {
|
|
936
1034
|
if (obj === null || typeof obj !== "object") return obj;
|
|
937
1035
|
if (Array.isArray(obj)) return obj.map(stripDangerousKeys);
|
|
@@ -994,6 +1092,35 @@ async function initDefaultConfig() {
|
|
|
994
1092
|
return { created, skipped };
|
|
995
1093
|
}
|
|
996
1094
|
|
|
1095
|
+
// src/errors.ts
|
|
1096
|
+
var SyncpointErrorCode = {
|
|
1097
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
1098
|
+
CONFIG_INVALID: "CONFIG_INVALID",
|
|
1099
|
+
BACKUP_FAILED: "BACKUP_FAILED",
|
|
1100
|
+
RESTORE_FAILED: "RESTORE_FAILED",
|
|
1101
|
+
TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND",
|
|
1102
|
+
PROVISION_FAILED: "PROVISION_FAILED",
|
|
1103
|
+
MISSING_ARGUMENT: "MISSING_ARGUMENT",
|
|
1104
|
+
INVALID_ARGUMENT: "INVALID_ARGUMENT",
|
|
1105
|
+
UNKNOWN: "UNKNOWN"
|
|
1106
|
+
};
|
|
1107
|
+
function classifyError(err) {
|
|
1108
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1109
|
+
if (msg.includes("Config file not found") || msg.includes('Run "syncpoint init"')) {
|
|
1110
|
+
return SyncpointErrorCode.CONFIG_NOT_FOUND;
|
|
1111
|
+
}
|
|
1112
|
+
if (msg.includes("Invalid config")) {
|
|
1113
|
+
return SyncpointErrorCode.CONFIG_INVALID;
|
|
1114
|
+
}
|
|
1115
|
+
if (msg.includes("Template not found") || msg.includes("template not found")) {
|
|
1116
|
+
return SyncpointErrorCode.TEMPLATE_NOT_FOUND;
|
|
1117
|
+
}
|
|
1118
|
+
if (msg.includes("Template file not found")) {
|
|
1119
|
+
return SyncpointErrorCode.TEMPLATE_NOT_FOUND;
|
|
1120
|
+
}
|
|
1121
|
+
return SyncpointErrorCode.UNKNOWN;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
997
1124
|
// src/utils/command-registry.ts
|
|
998
1125
|
var COMMANDS = {
|
|
999
1126
|
init: {
|
|
@@ -1009,7 +1136,8 @@ var COMMANDS = {
|
|
|
1009
1136
|
options: [
|
|
1010
1137
|
{
|
|
1011
1138
|
flag: "-p, --print",
|
|
1012
|
-
description: "Print prompt instead of invoking Claude Code"
|
|
1139
|
+
description: "Print prompt instead of invoking Claude Code",
|
|
1140
|
+
type: "boolean"
|
|
1013
1141
|
}
|
|
1014
1142
|
],
|
|
1015
1143
|
examples: [
|
|
@@ -1024,15 +1152,18 @@ var COMMANDS = {
|
|
|
1024
1152
|
options: [
|
|
1025
1153
|
{
|
|
1026
1154
|
flag: "--dry-run",
|
|
1027
|
-
description: "Preview files to be backed up without creating archive"
|
|
1155
|
+
description: "Preview files to be backed up without creating archive",
|
|
1156
|
+
type: "boolean"
|
|
1028
1157
|
},
|
|
1029
1158
|
{
|
|
1030
1159
|
flag: "--tag <name>",
|
|
1031
|
-
description: "Add custom tag to backup filename"
|
|
1160
|
+
description: "Add custom tag to backup filename",
|
|
1161
|
+
type: "string"
|
|
1032
1162
|
},
|
|
1033
1163
|
{
|
|
1034
1164
|
flag: "-v, --verbose",
|
|
1035
|
-
description: "Show detailed output including missing files"
|
|
1165
|
+
description: "Show detailed output including missing files",
|
|
1166
|
+
type: "boolean"
|
|
1036
1167
|
}
|
|
1037
1168
|
],
|
|
1038
1169
|
examples: [
|
|
@@ -1055,7 +1186,8 @@ var COMMANDS = {
|
|
|
1055
1186
|
options: [
|
|
1056
1187
|
{
|
|
1057
1188
|
flag: "--dry-run",
|
|
1058
|
-
description: "Show restore plan without actually restoring"
|
|
1189
|
+
description: "Show restore plan without actually restoring",
|
|
1190
|
+
type: "boolean"
|
|
1059
1191
|
}
|
|
1060
1192
|
],
|
|
1061
1193
|
examples: [
|
|
@@ -1078,15 +1210,18 @@ var COMMANDS = {
|
|
|
1078
1210
|
options: [
|
|
1079
1211
|
{
|
|
1080
1212
|
flag: "-f, --file <path>",
|
|
1081
|
-
description: "Path to template file (alternative to template name)"
|
|
1213
|
+
description: "Path to template file (alternative to template name)",
|
|
1214
|
+
type: "string"
|
|
1082
1215
|
},
|
|
1083
1216
|
{
|
|
1084
1217
|
flag: "--dry-run",
|
|
1085
|
-
description: "Show execution plan without running commands"
|
|
1218
|
+
description: "Show execution plan without running commands",
|
|
1219
|
+
type: "boolean"
|
|
1086
1220
|
},
|
|
1087
1221
|
{
|
|
1088
1222
|
flag: "--skip-restore",
|
|
1089
|
-
description: "Skip automatic config restore after provisioning"
|
|
1223
|
+
description: "Skip automatic config restore after provisioning",
|
|
1224
|
+
type: "boolean"
|
|
1090
1225
|
}
|
|
1091
1226
|
],
|
|
1092
1227
|
examples: [
|
|
@@ -1111,7 +1246,8 @@ var COMMANDS = {
|
|
|
1111
1246
|
options: [
|
|
1112
1247
|
{
|
|
1113
1248
|
flag: "-p, --print",
|
|
1114
|
-
description: "Print prompt instead of invoking Claude Code"
|
|
1249
|
+
description: "Print prompt instead of invoking Claude Code",
|
|
1250
|
+
type: "boolean"
|
|
1115
1251
|
}
|
|
1116
1252
|
],
|
|
1117
1253
|
examples: [
|
|
@@ -1131,7 +1267,7 @@ var COMMANDS = {
|
|
|
1131
1267
|
required: false
|
|
1132
1268
|
}
|
|
1133
1269
|
],
|
|
1134
|
-
options: [{ flag: "--delete <
|
|
1270
|
+
options: [{ flag: "--delete <filename>", description: "Delete item by filename", type: "string" }],
|
|
1135
1271
|
examples: [
|
|
1136
1272
|
"npx @lumy-pack/syncpoint list",
|
|
1137
1273
|
"npx @lumy-pack/syncpoint list backups",
|
|
@@ -1143,7 +1279,7 @@ var COMMANDS = {
|
|
|
1143
1279
|
description: "Show ~/.syncpoint/ status summary and manage cleanup",
|
|
1144
1280
|
usage: "npx @lumy-pack/syncpoint status [options]",
|
|
1145
1281
|
options: [
|
|
1146
|
-
{ flag: "--cleanup", description: "Enter interactive cleanup mode" }
|
|
1282
|
+
{ flag: "--cleanup", description: "Enter interactive cleanup mode", type: "boolean" }
|
|
1147
1283
|
],
|
|
1148
1284
|
examples: [
|
|
1149
1285
|
"npx @lumy-pack/syncpoint status",
|
|
@@ -1157,7 +1293,8 @@ var COMMANDS = {
|
|
|
1157
1293
|
options: [
|
|
1158
1294
|
{
|
|
1159
1295
|
flag: "--dry-run",
|
|
1160
|
-
description: "Preview changes without writing"
|
|
1296
|
+
description: "Preview changes without writing",
|
|
1297
|
+
type: "boolean"
|
|
1161
1298
|
}
|
|
1162
1299
|
],
|
|
1163
1300
|
examples: [
|
|
@@ -1334,6 +1471,33 @@ function registerBackupCommand(program2) {
|
|
|
1334
1471
|
});
|
|
1335
1472
|
cmd.action(
|
|
1336
1473
|
async (opts) => {
|
|
1474
|
+
const globalOpts = program2.opts();
|
|
1475
|
+
const startTime = Date.now();
|
|
1476
|
+
if (globalOpts.json) {
|
|
1477
|
+
try {
|
|
1478
|
+
const config = await loadConfig();
|
|
1479
|
+
const result = await createBackup(config, {
|
|
1480
|
+
dryRun: opts.dryRun,
|
|
1481
|
+
tag: opts.tag,
|
|
1482
|
+
verbose: opts.verbose
|
|
1483
|
+
});
|
|
1484
|
+
respond(
|
|
1485
|
+
"backup",
|
|
1486
|
+
{
|
|
1487
|
+
archivePath: result.archivePath,
|
|
1488
|
+
fileCount: result.metadata.summary.fileCount,
|
|
1489
|
+
totalSize: result.metadata.summary.totalSize,
|
|
1490
|
+
tag: opts.tag ?? null
|
|
1491
|
+
},
|
|
1492
|
+
startTime,
|
|
1493
|
+
VERSION
|
|
1494
|
+
);
|
|
1495
|
+
} catch (error) {
|
|
1496
|
+
const code = classifyError(error);
|
|
1497
|
+
respondError("backup", code, error.message, startTime, VERSION);
|
|
1498
|
+
}
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1337
1501
|
const { waitUntilExit } = render(
|
|
1338
1502
|
/* @__PURE__ */ jsx2(
|
|
1339
1503
|
BackupView,
|
|
@@ -1358,46 +1522,7 @@ import { Box as Box2, Text as Text3, useApp as useApp2 } from "ink";
|
|
|
1358
1522
|
import { render as render2 } from "ink";
|
|
1359
1523
|
import Spinner from "ink-spinner";
|
|
1360
1524
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1361
|
-
|
|
1362
|
-
// src/prompts/wizard-template.ts
|
|
1363
|
-
function generateTemplateWizardPrompt(variables) {
|
|
1364
|
-
return `You are a Syncpoint provisioning template assistant. Your role is to help users create automated environment setup templates.
|
|
1365
|
-
|
|
1366
|
-
**Input:**
|
|
1367
|
-
1. User's provisioning requirements (described in natural language)
|
|
1368
|
-
2. Example template structure (YAML)
|
|
1369
|
-
|
|
1370
|
-
**Your Task:**
|
|
1371
|
-
1. Ask clarifying questions to understand the provisioning workflow:
|
|
1372
|
-
- What software/tools need to be installed?
|
|
1373
|
-
- What dependencies should be checked?
|
|
1374
|
-
- Are there any configuration steps after installation?
|
|
1375
|
-
- Should any steps require sudo privileges?
|
|
1376
|
-
- Should any steps be conditional (skip_if)?
|
|
1377
|
-
2. Based on user responses, generate a complete provision template
|
|
1378
|
-
|
|
1379
|
-
**Output Requirements:**
|
|
1380
|
-
- Pure YAML format only (no markdown, no code blocks, no explanations)
|
|
1381
|
-
- Must be valid according to Syncpoint template schema
|
|
1382
|
-
- Required fields:
|
|
1383
|
-
- \`name\`: Template name
|
|
1384
|
-
- \`steps\`: Array of provisioning steps (minimum 1)
|
|
1385
|
-
- Each step must include:
|
|
1386
|
-
- \`name\`: Step name (required)
|
|
1387
|
-
- \`command\`: Shell command to execute (required)
|
|
1388
|
-
- \`description\`: Step description (optional)
|
|
1389
|
-
- \`skip_if\`: Condition to skip step (optional)
|
|
1390
|
-
- \`continue_on_error\`: Whether to continue on failure (optional, default: false)
|
|
1391
|
-
- Optional template fields:
|
|
1392
|
-
- \`description\`: Template description
|
|
1393
|
-
- \`backup\`: Backup name to restore after provisioning
|
|
1394
|
-
- \`sudo\`: Whether sudo is required (boolean)
|
|
1395
|
-
|
|
1396
|
-
**Example Template:**
|
|
1397
|
-
${variables.exampleTemplate}
|
|
1398
|
-
|
|
1399
|
-
Begin by asking the user to describe their provisioning needs.`;
|
|
1400
|
-
}
|
|
1525
|
+
init_wizard_template();
|
|
1401
1526
|
|
|
1402
1527
|
// assets/schemas/template.schema.json
|
|
1403
1528
|
var template_schema_default = {
|
|
@@ -1473,6 +1598,9 @@ function validateTemplate(data) {
|
|
|
1473
1598
|
return { valid: false, errors };
|
|
1474
1599
|
}
|
|
1475
1600
|
|
|
1601
|
+
// src/commands/CreateTemplate.tsx
|
|
1602
|
+
init_assets();
|
|
1603
|
+
|
|
1476
1604
|
// src/utils/claude-code-runner.ts
|
|
1477
1605
|
import { spawn } from "child_process";
|
|
1478
1606
|
async function isClaudeCodeAvailable() {
|
|
@@ -1797,6 +1925,30 @@ ${formatValidationErrors(validation.errors || [])}`
|
|
|
1797
1925
|
};
|
|
1798
1926
|
function registerCreateTemplateCommand(program2) {
|
|
1799
1927
|
program2.command("create-template [name]").description("Interactive wizard to create a provisioning template").option("-p, --print", "Print prompt instead of invoking Claude Code").action(async (name, opts) => {
|
|
1928
|
+
const globalOpts = program2.opts();
|
|
1929
|
+
const startTime = Date.now();
|
|
1930
|
+
if (globalOpts.json) {
|
|
1931
|
+
if (!opts.print) {
|
|
1932
|
+
respondError(
|
|
1933
|
+
"create-template",
|
|
1934
|
+
SyncpointErrorCode.MISSING_ARGUMENT,
|
|
1935
|
+
"--print is required in --json mode (interactive mode requires a terminal)",
|
|
1936
|
+
startTime,
|
|
1937
|
+
VERSION
|
|
1938
|
+
);
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
try {
|
|
1942
|
+
const { generateTemplateWizardPrompt: generateTemplateWizardPrompt2 } = await Promise.resolve().then(() => (init_wizard_template(), wizard_template_exports));
|
|
1943
|
+
const { readAsset: readAsset2 } = await Promise.resolve().then(() => (init_assets(), assets_exports));
|
|
1944
|
+
const exampleTemplate = readAsset2("template.example.yml");
|
|
1945
|
+
const prompt = generateTemplateWizardPrompt2({ exampleTemplate });
|
|
1946
|
+
respond("create-template", { prompt }, startTime, VERSION);
|
|
1947
|
+
} catch (err) {
|
|
1948
|
+
respondError("create-template", SyncpointErrorCode.UNKNOWN, err.message, startTime, VERSION);
|
|
1949
|
+
}
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1800
1952
|
const { waitUntilExit } = render2(
|
|
1801
1953
|
/* @__PURE__ */ jsx3(
|
|
1802
1954
|
CreateTemplateView,
|
|
@@ -1949,6 +2101,21 @@ var HelpView = ({ commandName }) => {
|
|
|
1949
2101
|
};
|
|
1950
2102
|
function registerHelpCommand(program2) {
|
|
1951
2103
|
program2.command("help [command]").description("Display help information").action(async (commandName) => {
|
|
2104
|
+
const globalOpts = program2.opts();
|
|
2105
|
+
const startTime = Date.now();
|
|
2106
|
+
if (globalOpts.json) {
|
|
2107
|
+
if (commandName) {
|
|
2108
|
+
const commandInfo = COMMANDS[commandName];
|
|
2109
|
+
if (!commandInfo) {
|
|
2110
|
+
respond("help", { error: `Unknown command: ${commandName}`, commands: Object.keys(COMMANDS) }, startTime, VERSION);
|
|
2111
|
+
} else {
|
|
2112
|
+
respond("help", { command: commandInfo }, startTime, VERSION);
|
|
2113
|
+
}
|
|
2114
|
+
} else {
|
|
2115
|
+
respond("help", { commands: COMMANDS }, startTime, VERSION);
|
|
2116
|
+
}
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
1952
2119
|
const { waitUntilExit } = render3(/* @__PURE__ */ jsx4(HelpView, { commandName }));
|
|
1953
2120
|
await waitUntilExit();
|
|
1954
2121
|
});
|
|
@@ -1959,6 +2126,7 @@ import { join as join9 } from "path";
|
|
|
1959
2126
|
import { Box as Box4, Text as Text5, useApp as useApp3 } from "ink";
|
|
1960
2127
|
import { render as render4 } from "ink";
|
|
1961
2128
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
2129
|
+
init_assets();
|
|
1962
2130
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1963
2131
|
var InitView = () => {
|
|
1964
2132
|
const { exit } = useApp3();
|
|
@@ -2062,6 +2230,18 @@ function registerInitCommand(program2) {
|
|
|
2062
2230
|
program2.command("init").description(
|
|
2063
2231
|
`Initialize ~/.${APP_NAME}/ directory structure and default config`
|
|
2064
2232
|
).action(async () => {
|
|
2233
|
+
const globalOpts = program2.opts();
|
|
2234
|
+
const startTime = Date.now();
|
|
2235
|
+
if (globalOpts.json) {
|
|
2236
|
+
try {
|
|
2237
|
+
const result = await initDefaultConfig();
|
|
2238
|
+
respond("init", { created: result.created, skipped: result.skipped }, startTime, VERSION);
|
|
2239
|
+
} catch (error) {
|
|
2240
|
+
const code = classifyError(error);
|
|
2241
|
+
respondError("init", code, error.message, startTime, VERSION);
|
|
2242
|
+
}
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2065
2245
|
const { waitUntilExit } = render4(/* @__PURE__ */ jsx5(InitView, {}));
|
|
2066
2246
|
await waitUntilExit();
|
|
2067
2247
|
});
|
|
@@ -2844,11 +3024,72 @@ var ListView = ({ type, deleteIndex }) => {
|
|
|
2844
3024
|
return null;
|
|
2845
3025
|
};
|
|
2846
3026
|
function registerListCommand(program2) {
|
|
2847
|
-
program2.command("list [type]").description("List backups and templates").option("--delete <
|
|
3027
|
+
program2.command("list [type]").description("List backups and templates").option("--delete <filename>", "Delete item by filename").action(async (type, opts) => {
|
|
3028
|
+
const globalOpts = program2.opts();
|
|
3029
|
+
const startTime = Date.now();
|
|
3030
|
+
if (globalOpts.json) {
|
|
3031
|
+
try {
|
|
3032
|
+
const config = await loadConfig();
|
|
3033
|
+
if (opts.delete) {
|
|
3034
|
+
const filename = opts.delete;
|
|
3035
|
+
const backupDirectory = config.backup.destination ? resolveTargetPath(config.backup.destination) : getSubDir("backups");
|
|
3036
|
+
const isTemplate = type === "templates";
|
|
3037
|
+
if (isTemplate) {
|
|
3038
|
+
const templates = await listTemplates();
|
|
3039
|
+
const match = templates.find(
|
|
3040
|
+
(t) => t.name === filename || t.name === filename.replace(/\.ya?ml$/, "")
|
|
3041
|
+
);
|
|
3042
|
+
if (!match) {
|
|
3043
|
+
respondError("list", SyncpointErrorCode.INVALID_ARGUMENT, `Template not found: ${filename}`, startTime, VERSION);
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3046
|
+
if (!isInsideDir(match.path, getSubDir("templates"))) {
|
|
3047
|
+
respondError("list", SyncpointErrorCode.INVALID_ARGUMENT, `Refusing to delete file outside templates directory: ${match.path}`, startTime, VERSION);
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
3050
|
+
unlinkSync(match.path);
|
|
3051
|
+
respond("list", { deleted: match.name, path: match.path }, startTime, VERSION);
|
|
3052
|
+
} else {
|
|
3053
|
+
const list2 = await getBackupList(config);
|
|
3054
|
+
const match = list2.find(
|
|
3055
|
+
(b) => b.filename === filename || b.filename.startsWith(filename)
|
|
3056
|
+
);
|
|
3057
|
+
if (!match) {
|
|
3058
|
+
respondError("list", SyncpointErrorCode.INVALID_ARGUMENT, `Backup not found: ${filename}`, startTime, VERSION);
|
|
3059
|
+
return;
|
|
3060
|
+
}
|
|
3061
|
+
if (!isInsideDir(match.path, backupDirectory)) {
|
|
3062
|
+
respondError("list", SyncpointErrorCode.INVALID_ARGUMENT, `Refusing to delete file outside backups directory: ${match.path}`, startTime, VERSION);
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
unlinkSync(match.path);
|
|
3066
|
+
respond("list", { deleted: match.filename, path: match.path }, startTime, VERSION);
|
|
3067
|
+
}
|
|
3068
|
+
return;
|
|
3069
|
+
}
|
|
3070
|
+
const showBackups = !type || type === "backups";
|
|
3071
|
+
const showTemplates = !type || type === "templates";
|
|
3072
|
+
const result = {};
|
|
3073
|
+
if (showBackups) {
|
|
3074
|
+
result.backups = await getBackupList(config);
|
|
3075
|
+
}
|
|
3076
|
+
if (showTemplates) {
|
|
3077
|
+
result.templates = await listTemplates();
|
|
3078
|
+
}
|
|
3079
|
+
respond("list", result, startTime, VERSION);
|
|
3080
|
+
} catch (error) {
|
|
3081
|
+
const code = classifyError(error);
|
|
3082
|
+
respondError("list", code, error.message, startTime, VERSION);
|
|
3083
|
+
}
|
|
3084
|
+
return;
|
|
3085
|
+
}
|
|
2848
3086
|
const deleteIndex = opts.delete ? parseInt(opts.delete, 10) : void 0;
|
|
2849
3087
|
if (deleteIndex !== void 0 && isNaN(deleteIndex)) {
|
|
2850
|
-
|
|
2851
|
-
|
|
3088
|
+
const { waitUntilExit: waitUntilExit2 } = render5(
|
|
3089
|
+
/* @__PURE__ */ jsx8(ListView, { type, deleteIndex: void 0 })
|
|
3090
|
+
);
|
|
3091
|
+
await waitUntilExit2();
|
|
3092
|
+
return;
|
|
2852
3093
|
}
|
|
2853
3094
|
const { waitUntilExit } = render5(
|
|
2854
3095
|
/* @__PURE__ */ jsx8(ListView, { type, deleteIndex })
|
|
@@ -2865,6 +3106,7 @@ import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
|
2865
3106
|
// src/core/migrate.ts
|
|
2866
3107
|
import { copyFile as copyFile2, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
2867
3108
|
import YAML4 from "yaml";
|
|
3109
|
+
init_assets();
|
|
2868
3110
|
function extractSchemaPaths(schema, prefix = []) {
|
|
2869
3111
|
const paths = [];
|
|
2870
3112
|
const properties = schema.properties;
|
|
@@ -3085,6 +3327,18 @@ var MigrateView = ({ dryRun }) => {
|
|
|
3085
3327
|
};
|
|
3086
3328
|
function registerMigrateCommand(program2) {
|
|
3087
3329
|
program2.command("migrate").description("Migrate config.yml to match the current schema").option("--dry-run", "Preview changes without writing").action(async (opts) => {
|
|
3330
|
+
const globalOpts = program2.opts();
|
|
3331
|
+
const startTime = Date.now();
|
|
3332
|
+
if (globalOpts.json) {
|
|
3333
|
+
try {
|
|
3334
|
+
const result = await migrateConfig({ dryRun: opts.dryRun ?? false });
|
|
3335
|
+
respond("migrate", result, startTime, VERSION);
|
|
3336
|
+
} catch (error) {
|
|
3337
|
+
const code = classifyError(error);
|
|
3338
|
+
respondError("migrate", code, error.message, startTime, VERSION);
|
|
3339
|
+
}
|
|
3340
|
+
return;
|
|
3341
|
+
}
|
|
3088
3342
|
const { waitUntilExit } = render6(
|
|
3089
3343
|
/* @__PURE__ */ jsx9(MigrateView, { dryRun: opts.dryRun ?? false })
|
|
3090
3344
|
);
|
|
@@ -3396,14 +3650,24 @@ function registerProvisionCommand(program2) {
|
|
|
3396
3650
|
false
|
|
3397
3651
|
).option("-f, --file <path>", "Path to template file").action(
|
|
3398
3652
|
async (templateName, opts) => {
|
|
3653
|
+
const globalOpts = program2.opts();
|
|
3654
|
+
const startTime = Date.now();
|
|
3399
3655
|
let templatePath;
|
|
3400
3656
|
if (opts.file) {
|
|
3401
3657
|
templatePath = resolveTargetPath(opts.file);
|
|
3402
3658
|
if (!await fileExists(templatePath)) {
|
|
3659
|
+
if (globalOpts.json) {
|
|
3660
|
+
respondError("provision", SyncpointErrorCode.TEMPLATE_NOT_FOUND, `Template file not found: ${opts.file}`, startTime, VERSION);
|
|
3661
|
+
return;
|
|
3662
|
+
}
|
|
3403
3663
|
console.error(`Template file not found: ${opts.file}`);
|
|
3404
3664
|
process.exit(1);
|
|
3405
3665
|
}
|
|
3406
3666
|
if (!templatePath.endsWith(".yml") && !templatePath.endsWith(".yaml")) {
|
|
3667
|
+
if (globalOpts.json) {
|
|
3668
|
+
respondError("provision", SyncpointErrorCode.INVALID_ARGUMENT, `Template file must have .yml or .yaml extension: ${opts.file}`, startTime, VERSION);
|
|
3669
|
+
return;
|
|
3670
|
+
}
|
|
3407
3671
|
console.error(
|
|
3408
3672
|
`Template file must have .yml or .yaml extension: ${opts.file}`
|
|
3409
3673
|
);
|
|
@@ -3415,11 +3679,19 @@ function registerProvisionCommand(program2) {
|
|
|
3415
3679
|
(t) => t.name === templateName || t.name === `${templateName}.yml` || t.config.name === templateName
|
|
3416
3680
|
);
|
|
3417
3681
|
if (!match) {
|
|
3682
|
+
if (globalOpts.json) {
|
|
3683
|
+
respondError("provision", SyncpointErrorCode.TEMPLATE_NOT_FOUND, `Template not found: ${templateName}`, startTime, VERSION);
|
|
3684
|
+
return;
|
|
3685
|
+
}
|
|
3418
3686
|
console.error(`Template not found: ${templateName}`);
|
|
3419
3687
|
process.exit(1);
|
|
3420
3688
|
}
|
|
3421
3689
|
templatePath = match.path;
|
|
3422
3690
|
} else {
|
|
3691
|
+
if (globalOpts.json) {
|
|
3692
|
+
respondError("provision", SyncpointErrorCode.MISSING_ARGUMENT, "Either <template> name or --file option must be provided", startTime, VERSION);
|
|
3693
|
+
return;
|
|
3694
|
+
}
|
|
3423
3695
|
console.error(
|
|
3424
3696
|
"Error: Either <template> name or --file option must be provided"
|
|
3425
3697
|
);
|
|
@@ -3431,6 +3703,30 @@ function registerProvisionCommand(program2) {
|
|
|
3431
3703
|
if (tmpl.sudo && !opts.dryRun) {
|
|
3432
3704
|
ensureSudo(tmpl.name);
|
|
3433
3705
|
}
|
|
3706
|
+
if (globalOpts.json) {
|
|
3707
|
+
try {
|
|
3708
|
+
const collectedSteps = [];
|
|
3709
|
+
const generator = runProvision(templatePath, {
|
|
3710
|
+
dryRun: opts.dryRun,
|
|
3711
|
+
skipRestore: opts.skipRestore
|
|
3712
|
+
});
|
|
3713
|
+
for await (const result of generator) {
|
|
3714
|
+
if (result.status !== "running") {
|
|
3715
|
+
collectedSteps.push(result);
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
respond(
|
|
3719
|
+
"provision",
|
|
3720
|
+
{ steps: collectedSteps, totalDuration: Date.now() - startTime },
|
|
3721
|
+
startTime,
|
|
3722
|
+
VERSION
|
|
3723
|
+
);
|
|
3724
|
+
} catch (error) {
|
|
3725
|
+
const code = classifyError(error);
|
|
3726
|
+
respondError("provision", code, error.message, startTime, VERSION);
|
|
3727
|
+
}
|
|
3728
|
+
return;
|
|
3729
|
+
}
|
|
3434
3730
|
const { waitUntilExit } = render7(
|
|
3435
3731
|
/* @__PURE__ */ jsx11(
|
|
3436
3732
|
ProvisionView,
|
|
@@ -3666,6 +3962,52 @@ var RestoreView = ({ filename, options }) => {
|
|
|
3666
3962
|
};
|
|
3667
3963
|
function registerRestoreCommand(program2) {
|
|
3668
3964
|
program2.command("restore [filename]").description("Restore config files from a backup").option("--dry-run", "Show planned changes without actual restore", false).action(async (filename, opts) => {
|
|
3965
|
+
const globalOpts = program2.opts();
|
|
3966
|
+
const startTime = Date.now();
|
|
3967
|
+
if (globalOpts.json) {
|
|
3968
|
+
if (!filename) {
|
|
3969
|
+
respondError(
|
|
3970
|
+
"restore",
|
|
3971
|
+
SyncpointErrorCode.MISSING_ARGUMENT,
|
|
3972
|
+
"filename argument is required in --json mode",
|
|
3973
|
+
startTime,
|
|
3974
|
+
VERSION
|
|
3975
|
+
);
|
|
3976
|
+
return;
|
|
3977
|
+
}
|
|
3978
|
+
try {
|
|
3979
|
+
const config = await loadConfig();
|
|
3980
|
+
const list2 = await getBackupList(config);
|
|
3981
|
+
const match = list2.find(
|
|
3982
|
+
(b) => b.filename === filename || b.filename.startsWith(filename)
|
|
3983
|
+
);
|
|
3984
|
+
if (!match) {
|
|
3985
|
+
respondError(
|
|
3986
|
+
"restore",
|
|
3987
|
+
SyncpointErrorCode.RESTORE_FAILED,
|
|
3988
|
+
`Backup not found: ${filename}`,
|
|
3989
|
+
startTime,
|
|
3990
|
+
VERSION
|
|
3991
|
+
);
|
|
3992
|
+
return;
|
|
3993
|
+
}
|
|
3994
|
+
const result = await restoreBackup(match.path, { dryRun: opts.dryRun });
|
|
3995
|
+
respond(
|
|
3996
|
+
"restore",
|
|
3997
|
+
{
|
|
3998
|
+
restoredFiles: result.restoredFiles,
|
|
3999
|
+
skippedFiles: result.skippedFiles,
|
|
4000
|
+
safetyBackupPath: result.safetyBackupPath ?? null
|
|
4001
|
+
},
|
|
4002
|
+
startTime,
|
|
4003
|
+
VERSION
|
|
4004
|
+
);
|
|
4005
|
+
} catch (error) {
|
|
4006
|
+
const code = classifyError(error);
|
|
4007
|
+
respondError("restore", code, error.message, startTime, VERSION);
|
|
4008
|
+
}
|
|
4009
|
+
return;
|
|
4010
|
+
}
|
|
3669
4011
|
const { waitUntilExit } = render8(
|
|
3670
4012
|
/* @__PURE__ */ jsx12(RestoreView, { filename, options: { dryRun: opts.dryRun } })
|
|
3671
4013
|
);
|
|
@@ -4080,6 +4422,34 @@ var StatusView = ({ cleanup }) => {
|
|
|
4080
4422
|
};
|
|
4081
4423
|
function registerStatusCommand(program2) {
|
|
4082
4424
|
program2.command("status").description(`Show ~/.${APP_NAME}/ status summary`).option("--cleanup", "Interactive cleanup mode", false).action(async (opts) => {
|
|
4425
|
+
const globalOpts = program2.opts();
|
|
4426
|
+
const startTime = Date.now();
|
|
4427
|
+
if (globalOpts.json) {
|
|
4428
|
+
try {
|
|
4429
|
+
const config = await loadConfig();
|
|
4430
|
+
const backupDirectory = config.backup.destination ? resolveTargetPath(config.backup.destination) : getSubDir("backups");
|
|
4431
|
+
const backupStats = getDirStats(backupDirectory);
|
|
4432
|
+
const templateStats = getDirStats(getSubDir("templates"));
|
|
4433
|
+
const scriptStats = getDirStats(getSubDir("scripts"));
|
|
4434
|
+
const logStats = getDirStats(getSubDir("logs"));
|
|
4435
|
+
const backupList = await getBackupList(config);
|
|
4436
|
+
const lastBackup = backupList.length > 0 ? backupList[0].createdAt : null;
|
|
4437
|
+
const oldestBackup = backupList.length > 0 ? backupList[backupList.length - 1].createdAt : null;
|
|
4438
|
+
const statusInfo = {
|
|
4439
|
+
backups: backupStats,
|
|
4440
|
+
templates: templateStats,
|
|
4441
|
+
scripts: scriptStats,
|
|
4442
|
+
logs: logStats,
|
|
4443
|
+
lastBackup: lastBackup ?? void 0,
|
|
4444
|
+
oldestBackup: oldestBackup ?? void 0
|
|
4445
|
+
};
|
|
4446
|
+
respond("status", statusInfo, startTime, VERSION);
|
|
4447
|
+
} catch (error) {
|
|
4448
|
+
const code = classifyError(error);
|
|
4449
|
+
respondError("status", code, error.message, startTime, VERSION);
|
|
4450
|
+
}
|
|
4451
|
+
return;
|
|
4452
|
+
}
|
|
4083
4453
|
const { waitUntilExit } = render9(/* @__PURE__ */ jsx13(StatusView, { cleanup: opts.cleanup }));
|
|
4084
4454
|
await waitUntilExit();
|
|
4085
4455
|
});
|
|
@@ -4137,6 +4507,9 @@ ${variables.defaultConfig}
|
|
|
4137
4507
|
**Start by greeting the user and asking about their backup priorities. After understanding their needs, write the config.yml file directly.**`;
|
|
4138
4508
|
}
|
|
4139
4509
|
|
|
4510
|
+
// src/commands/Wizard.tsx
|
|
4511
|
+
init_assets();
|
|
4512
|
+
|
|
4140
4513
|
// src/utils/file-scanner.ts
|
|
4141
4514
|
import { stat as stat3 } from "fs/promises";
|
|
4142
4515
|
import { join as join13 } from "path";
|
|
@@ -4494,6 +4867,27 @@ function registerWizardCommand(program2) {
|
|
|
4494
4867
|
cmd.option(opt.flag, opt.description);
|
|
4495
4868
|
});
|
|
4496
4869
|
cmd.action(async (opts) => {
|
|
4870
|
+
const globalOpts = program2.opts();
|
|
4871
|
+
const startTime = Date.now();
|
|
4872
|
+
if (globalOpts.json) {
|
|
4873
|
+
if (!opts.print) {
|
|
4874
|
+
respondError(
|
|
4875
|
+
"wizard",
|
|
4876
|
+
SyncpointErrorCode.MISSING_ARGUMENT,
|
|
4877
|
+
"--print is required in --json mode (interactive mode requires a terminal)",
|
|
4878
|
+
startTime,
|
|
4879
|
+
VERSION
|
|
4880
|
+
);
|
|
4881
|
+
return;
|
|
4882
|
+
}
|
|
4883
|
+
try {
|
|
4884
|
+
const scanResult = await runScanPhase();
|
|
4885
|
+
respond("wizard", { prompt: scanResult.prompt }, startTime, VERSION);
|
|
4886
|
+
} catch (err) {
|
|
4887
|
+
respondError("wizard", SyncpointErrorCode.UNKNOWN, err.message, startTime, VERSION);
|
|
4888
|
+
}
|
|
4889
|
+
return;
|
|
4890
|
+
}
|
|
4497
4891
|
if (opts.print) {
|
|
4498
4892
|
const { waitUntilExit } = render10(/* @__PURE__ */ jsx14(WizardView, { printMode: true }));
|
|
4499
4893
|
await waitUntilExit();
|
|
@@ -4530,7 +4924,7 @@ function registerWizardCommand(program2) {
|
|
|
4530
4924
|
var program = new Command();
|
|
4531
4925
|
program.name("syncpoint").description(
|
|
4532
4926
|
"Personal Environment Manager \u2014 Config backup/restore and machine provisioning CLI"
|
|
4533
|
-
).version(VERSION);
|
|
4927
|
+
).version(VERSION).option("--json", "Output structured JSON to stdout").option("--yes", "Skip confirmation prompts (non-interactive mode)");
|
|
4534
4928
|
registerInitCommand(program);
|
|
4535
4929
|
registerWizardCommand(program);
|
|
4536
4930
|
registerBackupCommand(program);
|
|
@@ -4541,7 +4935,34 @@ registerListCommand(program);
|
|
|
4541
4935
|
registerMigrateCommand(program);
|
|
4542
4936
|
registerStatusCommand(program);
|
|
4543
4937
|
registerHelpCommand(program);
|
|
4938
|
+
if (process.argv.includes("--describe")) {
|
|
4939
|
+
const startTime = Date.now();
|
|
4940
|
+
const globalOptions = [
|
|
4941
|
+
{ flag: "--json", description: "Output structured JSON to stdout", type: "boolean" },
|
|
4942
|
+
{ flag: "--yes", description: "Skip confirmation prompts (non-interactive mode)", type: "boolean" },
|
|
4943
|
+
{ flag: "--describe", description: "Print CLI schema as JSON and exit", type: "boolean" },
|
|
4944
|
+
{ flag: "-V, --version", description: "Output the version number", type: "boolean" },
|
|
4945
|
+
{ flag: "-h, --help", description: "Display help for command", type: "boolean" }
|
|
4946
|
+
];
|
|
4947
|
+
respond(
|
|
4948
|
+
"describe",
|
|
4949
|
+
{
|
|
4950
|
+
name: "syncpoint",
|
|
4951
|
+
version: VERSION,
|
|
4952
|
+
description: program.description(),
|
|
4953
|
+
globalOptions,
|
|
4954
|
+
commands: COMMANDS
|
|
4955
|
+
},
|
|
4956
|
+
startTime,
|
|
4957
|
+
VERSION
|
|
4958
|
+
);
|
|
4959
|
+
process.exit(0);
|
|
4960
|
+
}
|
|
4544
4961
|
program.parseAsync(process.argv).catch((error) => {
|
|
4962
|
+
if (process.argv.includes("--json")) {
|
|
4963
|
+
respondError("unknown", SyncpointErrorCode.UNKNOWN, error.message, Date.now(), VERSION);
|
|
4964
|
+
process.exit(1);
|
|
4965
|
+
}
|
|
4545
4966
|
console.error("Fatal error:", error.message);
|
|
4546
4967
|
process.exit(1);
|
|
4547
4968
|
});
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const SyncpointErrorCode: {
|
|
2
|
+
readonly CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND";
|
|
3
|
+
readonly CONFIG_INVALID: "CONFIG_INVALID";
|
|
4
|
+
readonly BACKUP_FAILED: "BACKUP_FAILED";
|
|
5
|
+
readonly RESTORE_FAILED: "RESTORE_FAILED";
|
|
6
|
+
readonly TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND";
|
|
7
|
+
readonly PROVISION_FAILED: "PROVISION_FAILED";
|
|
8
|
+
readonly MISSING_ARGUMENT: "MISSING_ARGUMENT";
|
|
9
|
+
readonly INVALID_ARGUMENT: "INVALID_ARGUMENT";
|
|
10
|
+
readonly UNKNOWN: "UNKNOWN";
|
|
11
|
+
};
|
|
12
|
+
export type SyncpointErrorCode = (typeof SyncpointErrorCode)[keyof typeof SyncpointErrorCode];
|
|
13
|
+
/**
|
|
14
|
+
* Classify an error into a SyncpointErrorCode based on the error message.
|
|
15
|
+
*/
|
|
16
|
+
export declare function classifyError(err: unknown): SyncpointErrorCode;
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/version.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumy-pack/syncpoint",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "CLI tool for project synchronization and scaffolding",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -56,7 +56,6 @@
|
|
|
56
56
|
"version:patch": "yarn version patch"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@lumy-pack/shared": "0.0.1",
|
|
60
59
|
"ajv": "^8.0.0",
|
|
61
60
|
"ajv-formats": "^3.0.0",
|
|
62
61
|
"commander": "^12.1.0",
|
|
@@ -71,6 +70,7 @@
|
|
|
71
70
|
"yaml": "^2.0.0"
|
|
72
71
|
},
|
|
73
72
|
"devDependencies": {
|
|
73
|
+
"@lumy-pack/shared": "0.0.1",
|
|
74
74
|
"@types/micromatch": "^4.0.9",
|
|
75
75
|
"@types/node": "^20.11.0",
|
|
76
76
|
"@types/react": "^18.0.0",
|