@envmanager-cli/cli 0.2.0 → 0.2.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.
- package/dist/bin/envmanager.js +112 -21
- package/dist/bin/envmanager.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/envmanager.js
CHANGED
|
@@ -616,7 +616,8 @@ var ConfigSchema = z.object({
|
|
|
616
616
|
format: z.enum(EXPORT_FORMATS).optional(),
|
|
617
617
|
k8s_namespace: z.string().optional(),
|
|
618
618
|
k8s_name: z.string().optional(),
|
|
619
|
-
tags: z.array(z.string()).optional()
|
|
619
|
+
tags: z.array(z.string()).optional(),
|
|
620
|
+
service: z.string().optional()
|
|
620
621
|
});
|
|
621
622
|
var CONFIG_FILENAMES = ["envmanager.json", ".envmanagerrc"];
|
|
622
623
|
function findConfigFile(startDir = process.cwd()) {
|
|
@@ -726,6 +727,15 @@ async function detectOrgFromProject(projectInput, client, memberships) {
|
|
|
726
727
|
if (data && data.length === 1) return data[0].organization_id;
|
|
727
728
|
return null;
|
|
728
729
|
}
|
|
730
|
+
async function resolveServiceId(serviceName, client, projectId) {
|
|
731
|
+
const { data, error } = await client.from("services").select("id").eq("project_id", projectId).ilike("name", serviceName).single();
|
|
732
|
+
if (error || !data) {
|
|
733
|
+
const { data: allServices } = await client.from("services").select("name").eq("project_id", projectId).order("sort_order");
|
|
734
|
+
const available = allServices?.map((s) => s.name).join(", ") || "none";
|
|
735
|
+
throw new Error(`Service "${serviceName}" not found in project. Available services: ${available}`);
|
|
736
|
+
}
|
|
737
|
+
return data.id;
|
|
738
|
+
}
|
|
729
739
|
|
|
730
740
|
// src/lib/variable-references.ts
|
|
731
741
|
var REFERENCE_PATTERN = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
@@ -886,7 +896,7 @@ function resolveAll(variables) {
|
|
|
886
896
|
}
|
|
887
897
|
|
|
888
898
|
// src/commands/pull.ts
|
|
889
|
-
var pullCommand = new Command4("pull").description("Pull environment variables from EnvManager to local .env file").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: from config or "development")').option("-p, --project <id>", "Project ID (default: from config)").option("-o, --output <file>", "Output file path (default: .env)").option("--no-secrets", "Exclude secret values (will be empty)").option("-f, --force", "Overwrite existing file without prompting").option("-r, --resolve-references", "Resolve ${VAR} references to their values").option("-F, --include-fallbacks", "Include fallback values for empty variables").option("-s, --show-sources", "Show value source as inline comments").option("--format <type>", `Export format (${EXPORT_FORMATS.join(", ")})`).option("--k8s-namespace <ns>", 'Kubernetes namespace (default: "default")').option("--k8s-name <name>", "Kubernetes resource name").option("--tag <tags...>", "Filter by tags (untagged variables always included)").action(async (options) => {
|
|
899
|
+
var pullCommand = new Command4("pull").description("Pull environment variables from EnvManager to local .env file").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: from config or "development")').option("-p, --project <id>", "Project ID (default: from config)").option("-o, --output <file>", "Output file path (default: .env)").option("--no-secrets", "Exclude secret values (will be empty)").option("-f, --force", "Overwrite existing file without prompting").option("-r, --resolve-references", "Resolve ${VAR} references to their values").option("-F, --include-fallbacks", "Include fallback values for empty variables").option("-s, --show-sources", "Show value source as inline comments").option("--format <type>", `Export format (${EXPORT_FORMATS.join(", ")})`).option("--k8s-namespace <ns>", 'Kubernetes namespace (default: "default")').option("--k8s-name <name>", "Kubernetes resource name").option("--tag <tags...>", "Filter by tags (untagged variables always included)").option("--service <name>", "Filter by service name").action(async (options) => {
|
|
890
900
|
const spinner = ora3("Connecting to EnvManager...").start();
|
|
891
901
|
try {
|
|
892
902
|
const config = loadConfig();
|
|
@@ -924,6 +934,16 @@ var pullCommand = new Command4("pull").description("Pull environment variables f
|
|
|
924
934
|
spinner.fail(error instanceof Error ? error.message : "Failed to resolve project");
|
|
925
935
|
process.exit(1);
|
|
926
936
|
}
|
|
937
|
+
const serviceName = options.service || config?.service;
|
|
938
|
+
let serviceId;
|
|
939
|
+
if (serviceName) {
|
|
940
|
+
try {
|
|
941
|
+
serviceId = await resolveServiceId(serviceName, client, projectId);
|
|
942
|
+
} catch (error) {
|
|
943
|
+
spinner.fail(error instanceof Error ? error.message : "Failed to resolve service");
|
|
944
|
+
process.exit(1);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
927
947
|
spinner.text = "Fetching environment...";
|
|
928
948
|
const { data: environments, error: envError } = await client.from("environments").select("id, name").eq("project_id", projectId).ilike("name", envName).single();
|
|
929
949
|
if (envError || !environments) {
|
|
@@ -939,7 +959,8 @@ var pullCommand = new Command4("pull").description("Pull environment variables f
|
|
|
939
959
|
p_environment_id: environmentId,
|
|
940
960
|
p_sync_secrets: includeSecrets,
|
|
941
961
|
p_sync_variables: true,
|
|
942
|
-
p_include_fallbacks: shouldFallback || false
|
|
962
|
+
p_include_fallbacks: shouldFallback || false,
|
|
963
|
+
...serviceId && { p_service_id: serviceId }
|
|
943
964
|
};
|
|
944
965
|
const { data: variables, error: varError } = await client.rpc("get_variables_for_sync", rpcParams);
|
|
945
966
|
if (varError) {
|
|
@@ -1039,8 +1060,9 @@ File ${outputFile} already exists.`));
|
|
|
1039
1060
|
writeFileSync2(outputFile, content + "\n");
|
|
1040
1061
|
const secretCount = vars.filter((v) => v.is_secret).length;
|
|
1041
1062
|
const plainCount = vars.length - secretCount;
|
|
1063
|
+
const serviceInfo = serviceName ? ` (service: ${serviceName})` : "";
|
|
1042
1064
|
const tagInfo = filterTags.length > 0 ? ` (tags: ${filterTags.join(", ")})` : "";
|
|
1043
|
-
spinner.succeed(`Pulled ${vars.length} variables to ${outputFile} (${format})${tagInfo}`);
|
|
1065
|
+
spinner.succeed(`Pulled ${vars.length} variables to ${outputFile} (${format})${serviceInfo}${tagInfo}`);
|
|
1044
1066
|
console.log(chalk4.gray(` ${plainCount} plain, ${secretCount} secrets`));
|
|
1045
1067
|
client.rpc("log_variable_access", {
|
|
1046
1068
|
p_environment_id: environmentId,
|
|
@@ -1197,7 +1219,7 @@ function validateVariableName(name, config) {
|
|
|
1197
1219
|
}
|
|
1198
1220
|
|
|
1199
1221
|
// src/commands/push.ts
|
|
1200
|
-
var pushCommand = new Command5("push").description("Push local .env file to EnvManager").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: from config or "development")').option("-p, --project <id>", "Project ID (default: from config)").option("-i, --input <file>", "Input file path (default: .env)").option("--secrets <keys>", "Comma-separated list of keys to mark as secrets").option("--all-secrets", "Mark all variables as secrets").option("--dry-run", "Show what would be pushed without making changes").action(async (options) => {
|
|
1222
|
+
var pushCommand = new Command5("push").description("Push local .env file to EnvManager").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: from config or "development")').option("-p, --project <id>", "Project ID (default: from config)").option("-i, --input <file>", "Input file path (default: .env)").option("--secrets <keys>", "Comma-separated list of keys to mark as secrets").option("--all-secrets", "Mark all variables as secrets").option("--service <name>", "Push to specific service").option("--dry-run", "Show what would be pushed without making changes").action(async (options) => {
|
|
1201
1223
|
const spinner = ora4("Reading .env file...").start();
|
|
1202
1224
|
try {
|
|
1203
1225
|
const config = loadConfig();
|
|
@@ -1248,6 +1270,16 @@ var pushCommand = new Command5("push").description("Push local .env file to EnvM
|
|
|
1248
1270
|
spinner.fail(error instanceof Error ? error.message : "Failed to resolve project");
|
|
1249
1271
|
process.exit(1);
|
|
1250
1272
|
}
|
|
1273
|
+
const serviceName = options.service || config?.service;
|
|
1274
|
+
let serviceId;
|
|
1275
|
+
if (serviceName) {
|
|
1276
|
+
try {
|
|
1277
|
+
serviceId = await resolveServiceId(serviceName, client, projectId);
|
|
1278
|
+
} catch (error) {
|
|
1279
|
+
spinner.fail(error instanceof Error ? error.message : "Failed to resolve service");
|
|
1280
|
+
process.exit(1);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1251
1283
|
spinner.text = "Fetching environment...";
|
|
1252
1284
|
const { data: environment, error: envError } = await client.from("environments").select("id, name, project_id").eq("project_id", projectId).ilike("name", envName).single();
|
|
1253
1285
|
if (envError || !environment) {
|
|
@@ -1303,12 +1335,24 @@ var pushCommand = new Command5("push").description("Push local .env file to EnvM
|
|
|
1303
1335
|
key: v.key,
|
|
1304
1336
|
value: v.value
|
|
1305
1337
|
}));
|
|
1306
|
-
|
|
1338
|
+
let existingQuery = client.from("variables").select("key").eq("environment_id", environment.id);
|
|
1339
|
+
if (serviceId) {
|
|
1340
|
+
existingQuery = existingQuery.eq("service_id", serviceId);
|
|
1341
|
+
} else {
|
|
1342
|
+
existingQuery = existingQuery.is("service_id", null);
|
|
1343
|
+
}
|
|
1344
|
+
const { data: existingVars } = await existingQuery;
|
|
1307
1345
|
const existingKeys = new Set((existingVars || []).map((v) => v.key));
|
|
1308
1346
|
const keysToUpdate = variablesData.filter((v) => existingKeys.has(v.key));
|
|
1309
1347
|
const keysToInsert = variablesData.filter((v) => !existingKeys.has(v.key));
|
|
1310
1348
|
if (keysToUpdate.length > 0) {
|
|
1311
|
-
|
|
1349
|
+
let deleteQuery = client.from("variables").delete().eq("environment_id", environment.id).in("key", keysToUpdate.map((v) => v.key));
|
|
1350
|
+
if (serviceId) {
|
|
1351
|
+
deleteQuery = deleteQuery.eq("service_id", serviceId);
|
|
1352
|
+
} else {
|
|
1353
|
+
deleteQuery = deleteQuery.is("service_id", null);
|
|
1354
|
+
}
|
|
1355
|
+
const { error: deleteError } = await deleteQuery;
|
|
1312
1356
|
if (deleteError) {
|
|
1313
1357
|
spinner.fail("Failed to update existing variables");
|
|
1314
1358
|
console.error(chalk6.red(deleteError.message));
|
|
@@ -1319,14 +1363,16 @@ var pushCommand = new Command5("push").description("Push local .env file to EnvM
|
|
|
1319
1363
|
variables_data: variablesData,
|
|
1320
1364
|
environment_id_param: environment.id,
|
|
1321
1365
|
organization_id_param: organizationId,
|
|
1322
|
-
import_as_secrets: markAsSecrets
|
|
1366
|
+
import_as_secrets: markAsSecrets,
|
|
1367
|
+
...serviceId && { service_id_param: serviceId }
|
|
1323
1368
|
});
|
|
1324
1369
|
if (pushError) {
|
|
1325
1370
|
spinner.fail("Push failed");
|
|
1326
1371
|
console.error(chalk6.red(pushError.message));
|
|
1327
1372
|
process.exit(1);
|
|
1328
1373
|
}
|
|
1329
|
-
|
|
1374
|
+
const serviceInfo = serviceName ? ` (service: ${serviceName})` : "";
|
|
1375
|
+
spinner.succeed(`Pushed ${vars.length} variables to ${envName}${serviceInfo}`);
|
|
1330
1376
|
if (keysToUpdate.length > 0) {
|
|
1331
1377
|
console.log(chalk6.gray(` ${keysToInsert.length} inserted, ${keysToUpdate.length} updated`));
|
|
1332
1378
|
}
|
|
@@ -1739,14 +1785,16 @@ async function subscribeToVariableChanges(environmentId, onEvent, onStatus) {
|
|
|
1739
1785
|
});
|
|
1740
1786
|
return subscription;
|
|
1741
1787
|
}
|
|
1742
|
-
async function fetchAllVariables(environmentId, includeSecrets = true) {
|
|
1788
|
+
async function fetchAllVariables(environmentId, includeSecrets = true, serviceId) {
|
|
1743
1789
|
const client = await createClient();
|
|
1744
|
-
const
|
|
1790
|
+
const rpcParams = {
|
|
1745
1791
|
p_environment_id: environmentId,
|
|
1746
1792
|
p_sync_secrets: includeSecrets,
|
|
1747
1793
|
p_sync_variables: true,
|
|
1748
|
-
p_include_fallbacks: false
|
|
1749
|
-
|
|
1794
|
+
p_include_fallbacks: false,
|
|
1795
|
+
...serviceId && { p_service_id: serviceId }
|
|
1796
|
+
};
|
|
1797
|
+
const { data: variables, error } = await client.rpc("get_variables_for_sync", rpcParams);
|
|
1750
1798
|
if (error) {
|
|
1751
1799
|
throw new Error(`Failed to fetch variables: ${error.message}`);
|
|
1752
1800
|
}
|
|
@@ -1888,7 +1936,7 @@ function mergeWithRemote(local, remoteVariables, strategy) {
|
|
|
1888
1936
|
}
|
|
1889
1937
|
|
|
1890
1938
|
// src/commands/dev.ts
|
|
1891
|
-
var devCommand = new Command9("dev").description("Start real-time sync daemon - watches for remote variable changes").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: from config or "development")').option("-p, --project <id>", "Project ID (default: from config)").option("--output <file>", "Output file path (default: .env)").option("--no-watch", "Disable local file watching").option("--strategy <type>", "Merge strategy: remote_wins, local_wins, merge_new (default: remote_wins)", "remote_wins").option("--tag <tags...>", "Filter by tags (untagged variables always included)").action(async (options) => {
|
|
1939
|
+
var devCommand = new Command9("dev").description("Start real-time sync daemon - watches for remote variable changes").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: from config or "development")').option("-p, --project <id>", "Project ID (default: from config)").option("--output <file>", "Output file path (default: .env)").option("--no-watch", "Disable local file watching").option("--strategy <type>", "Merge strategy: remote_wins, local_wins, merge_new (default: remote_wins)", "remote_wins").option("--tag <tags...>", "Filter by tags (untagged variables always included)").option("--service <name>", "Filter by service name").action(async (options) => {
|
|
1892
1940
|
const spinner = ora7("Starting dev mode...").start();
|
|
1893
1941
|
try {
|
|
1894
1942
|
const config = loadConfig();
|
|
@@ -1918,6 +1966,16 @@ var devCommand = new Command9("dev").description("Start real-time sync daemon -
|
|
|
1918
1966
|
spinner.fail(error instanceof Error ? error.message : "Failed to resolve project");
|
|
1919
1967
|
process.exit(1);
|
|
1920
1968
|
}
|
|
1969
|
+
const serviceName = options.service || config?.service;
|
|
1970
|
+
let serviceId;
|
|
1971
|
+
if (serviceName) {
|
|
1972
|
+
try {
|
|
1973
|
+
serviceId = await resolveServiceId(serviceName, client, projectId);
|
|
1974
|
+
} catch (error) {
|
|
1975
|
+
spinner.fail(error instanceof Error ? error.message : "Failed to resolve service");
|
|
1976
|
+
process.exit(1);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1921
1979
|
spinner.text = "Fetching environment...";
|
|
1922
1980
|
const { data: environment, error: envError } = await client.from("environments").select("id, name, project_id").eq("project_id", projectId).ilike("name", envName).single();
|
|
1923
1981
|
if (envError || !environment) {
|
|
@@ -1934,7 +1992,7 @@ var devCommand = new Command9("dev").description("Start real-time sync daemon -
|
|
|
1934
1992
|
});
|
|
1935
1993
|
};
|
|
1936
1994
|
spinner.text = "Performing initial sync...";
|
|
1937
|
-
const remoteVariables = applyTagFilter(await fetchAllVariables(environmentId, true));
|
|
1995
|
+
const remoteVariables = applyTagFilter(await fetchAllVariables(environmentId, true, serviceId));
|
|
1938
1996
|
let localVariables = /* @__PURE__ */ new Map();
|
|
1939
1997
|
if (existsSync7(outputFile)) {
|
|
1940
1998
|
const content = readFileSync6(outputFile, "utf-8");
|
|
@@ -1951,7 +2009,7 @@ var devCommand = new Command9("dev").description("Start real-time sync daemon -
|
|
|
1951
2009
|
let isPaused = false;
|
|
1952
2010
|
let lastRemoteKeys = null;
|
|
1953
2011
|
async function syncRemoteToLocal(silent = false) {
|
|
1954
|
-
const updatedVariables = applyTagFilter(await fetchAllVariables(environmentId, true));
|
|
2012
|
+
const updatedVariables = applyTagFilter(await fetchAllVariables(environmentId, true, serviceId));
|
|
1955
2013
|
const currentLocal = /* @__PURE__ */ new Map();
|
|
1956
2014
|
if (existsSync7(outputFile)) {
|
|
1957
2015
|
const content = readFileSync6(outputFile, "utf-8");
|
|
@@ -2043,6 +2101,9 @@ Realtime error: ${message || ""}`));
|
|
|
2043
2101
|
console.log("");
|
|
2044
2102
|
console.log(chalk10.cyan(" Project:"), projectId);
|
|
2045
2103
|
console.log(chalk10.cyan(" Environment:"), envName);
|
|
2104
|
+
if (serviceName) {
|
|
2105
|
+
console.log(chalk10.cyan(" Service:"), serviceName);
|
|
2106
|
+
}
|
|
2046
2107
|
console.log(chalk10.cyan(" Output:"), outputFile);
|
|
2047
2108
|
console.log(chalk10.cyan(" Strategy:"), strategy);
|
|
2048
2109
|
console.log(chalk10.cyan(" Watching:"), watchLocal ? "local + remote" : "remote only");
|
|
@@ -2347,7 +2408,7 @@ function generateYamlTemplate(variables, options = {}) {
|
|
|
2347
2408
|
}
|
|
2348
2409
|
|
|
2349
2410
|
// src/commands/init.ts
|
|
2350
|
-
var initCommand = new Command10("init").description("Initialize project configuration and generate .env.template from EnvManager").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: "development")').option("-p, --project <id>", "Project ID").option("--format <type>", "Template format: simple or yaml (default: simple)", "simple").option("-f, --force", "Overwrite existing files without prompting").action(async (options) => {
|
|
2411
|
+
var initCommand = new Command10("init").description("Initialize project configuration and generate .env.template from EnvManager").option("--org <name>", "Organization name (required if you belong to multiple)").option("-e, --environment <name>", 'Environment name (default: "development")').option("-p, --project <id>", "Project ID").option("--format <type>", "Template format: simple or yaml (default: simple)", "simple").option("-f, --force", "Overwrite existing files without prompting").option("--service <name>", "Service name to scope variables to").action(async (options) => {
|
|
2351
2412
|
const spinner = ora8("Initializing project...").start();
|
|
2352
2413
|
try {
|
|
2353
2414
|
const configPath = resolve5("envmanager.json");
|
|
@@ -2408,13 +2469,39 @@ Environment "${envName}" not found. Available:`));
|
|
|
2408
2469
|
}
|
|
2409
2470
|
process.exit(1);
|
|
2410
2471
|
}
|
|
2472
|
+
let selectedServiceName;
|
|
2473
|
+
let serviceIdForSync;
|
|
2474
|
+
const { data: projectServices } = await client.from("services").select("id, name").eq("project_id", projectId).order("sort_order");
|
|
2475
|
+
if (options.service) {
|
|
2476
|
+
spinner.text = "Resolving service...";
|
|
2477
|
+
try {
|
|
2478
|
+
serviceIdForSync = await resolveServiceId(options.service, client, projectId);
|
|
2479
|
+
selectedServiceName = options.service;
|
|
2480
|
+
} catch (error) {
|
|
2481
|
+
spinner.fail(error instanceof Error ? error.message : "Failed to resolve service");
|
|
2482
|
+
process.exit(1);
|
|
2483
|
+
}
|
|
2484
|
+
} else if (projectServices && projectServices.length > 0) {
|
|
2485
|
+
spinner.stop();
|
|
2486
|
+
console.log("");
|
|
2487
|
+
console.log(chalk11.cyan("Services available in this project:"));
|
|
2488
|
+
projectServices.forEach((s) => {
|
|
2489
|
+
console.log(chalk11.gray(` - ${s.name}`));
|
|
2490
|
+
});
|
|
2491
|
+
console.log(chalk11.gray("\n Use --service <name> to scope variables to a specific service."));
|
|
2492
|
+
console.log(chalk11.gray(" Without --service, all variables will be synced."));
|
|
2493
|
+
console.log("");
|
|
2494
|
+
spinner.start("Fetching variables...");
|
|
2495
|
+
}
|
|
2411
2496
|
spinner.text = "Fetching variables...";
|
|
2412
|
-
const
|
|
2497
|
+
const rpcParams = {
|
|
2413
2498
|
p_environment_id: environment.id,
|
|
2414
2499
|
p_sync_secrets: false,
|
|
2415
2500
|
p_sync_variables: true,
|
|
2416
|
-
p_include_fallbacks: false
|
|
2417
|
-
|
|
2501
|
+
p_include_fallbacks: false,
|
|
2502
|
+
...serviceIdForSync && { p_service_id: serviceIdForSync }
|
|
2503
|
+
};
|
|
2504
|
+
const { data: variables, error: varError } = await client.rpc("get_variables_for_sync", rpcParams);
|
|
2418
2505
|
if (varError) {
|
|
2419
2506
|
spinner.fail("Failed to fetch variables");
|
|
2420
2507
|
console.error(chalk11.red(varError.message));
|
|
@@ -2438,6 +2525,9 @@ File ${templatePath} already exists. Use --force to overwrite.`));
|
|
|
2438
2525
|
project_id: projectId,
|
|
2439
2526
|
environment: environment.name
|
|
2440
2527
|
};
|
|
2528
|
+
if (selectedServiceName) {
|
|
2529
|
+
config.service = selectedServiceName;
|
|
2530
|
+
}
|
|
2441
2531
|
writeFileSync4(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
2442
2532
|
const templateVars = varsArray.map((v) => ({
|
|
2443
2533
|
key: v.key,
|
|
@@ -2451,7 +2541,8 @@ File ${templatePath} already exists. Use --force to overwrite.`));
|
|
|
2451
2541
|
const simpleContent = generateTemplate(templateVars, { includeDefaults: true });
|
|
2452
2542
|
writeFileSync4(templatePath, simpleContent);
|
|
2453
2543
|
}
|
|
2454
|
-
|
|
2544
|
+
const serviceInfo = selectedServiceName ? ` (service: ${selectedServiceName})` : "";
|
|
2545
|
+
spinner.succeed(`Project initialized${serviceInfo}`);
|
|
2455
2546
|
console.log("");
|
|
2456
2547
|
console.log(chalk11.green("Created:"));
|
|
2457
2548
|
console.log(chalk11.gray(` ${configPath}`));
|