cf-envsync 0.3.13 → 0.3.15
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/index.js +206 -9
- package/package.json +1 -1
- package/src/types/config.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -2286,9 +2286,6 @@ function validateConfig(config) {
|
|
|
2286
2286
|
if (!app.path) {
|
|
2287
2287
|
errors.push(`App "${name}" is missing "path" field`);
|
|
2288
2288
|
}
|
|
2289
|
-
if (!app.workers || Object.keys(app.workers).length === 0) {
|
|
2290
|
-
errors.push(`App "${name}" is missing "workers" mapping`);
|
|
2291
|
-
}
|
|
2292
2289
|
if ((!app.secrets || app.secrets.length === 0) && (!app.vars || app.vars.length === 0)) {
|
|
2293
2290
|
errors.push(`App "${name}" has no "secrets" or "vars" declared`);
|
|
2294
2291
|
}
|
|
@@ -2355,7 +2352,7 @@ function resolveApps(config, appNames) {
|
|
|
2355
2352
|
return resolved;
|
|
2356
2353
|
}
|
|
2357
2354
|
function getWorkerName(app, environment) {
|
|
2358
|
-
return app.workers[environment];
|
|
2355
|
+
return app.workers?.[environment];
|
|
2359
2356
|
}
|
|
2360
2357
|
function resolveEnvFilePath(pattern, env2) {
|
|
2361
2358
|
if (env2 === "local")
|
|
@@ -13755,6 +13752,120 @@ ${envIndent}"env": ${inner}
|
|
|
13755
13752
|
await writeFile(configPath, content);
|
|
13756
13753
|
return { success: true, filePath: configPath, updatedCount: Object.keys(vars).length };
|
|
13757
13754
|
}
|
|
13755
|
+
function findFullKeyRange(text, key, searchStart = 0) {
|
|
13756
|
+
const needle = `"${key}"`;
|
|
13757
|
+
let i2 = searchStart;
|
|
13758
|
+
let inString = false;
|
|
13759
|
+
while (i2 < text.length) {
|
|
13760
|
+
if (inString) {
|
|
13761
|
+
if (text[i2] === "\\" && i2 + 1 < text.length) {
|
|
13762
|
+
i2 += 2;
|
|
13763
|
+
continue;
|
|
13764
|
+
}
|
|
13765
|
+
if (text[i2] === '"')
|
|
13766
|
+
inString = false;
|
|
13767
|
+
i2++;
|
|
13768
|
+
continue;
|
|
13769
|
+
}
|
|
13770
|
+
if (text[i2] === "/" && text[i2 + 1] === "/") {
|
|
13771
|
+
while (i2 < text.length && text[i2] !== `
|
|
13772
|
+
`)
|
|
13773
|
+
i2++;
|
|
13774
|
+
continue;
|
|
13775
|
+
}
|
|
13776
|
+
if (text[i2] === "/" && text[i2 + 1] === "*") {
|
|
13777
|
+
i2 += 2;
|
|
13778
|
+
while (i2 < text.length && !(text[i2] === "*" && text[i2 + 1] === "/"))
|
|
13779
|
+
i2++;
|
|
13780
|
+
i2 += 2;
|
|
13781
|
+
continue;
|
|
13782
|
+
}
|
|
13783
|
+
if (text.startsWith(needle, i2)) {
|
|
13784
|
+
const keyStart = i2;
|
|
13785
|
+
let j = i2 + needle.length;
|
|
13786
|
+
while (j < text.length && (text[j] === " " || text[j] === "\t" || text[j] === `
|
|
13787
|
+
` || text[j] === "\r"))
|
|
13788
|
+
j++;
|
|
13789
|
+
if (text[j] === ":") {
|
|
13790
|
+
j++;
|
|
13791
|
+
while (j < text.length && (text[j] === " " || text[j] === "\t" || text[j] === `
|
|
13792
|
+
` || text[j] === "\r"))
|
|
13793
|
+
j++;
|
|
13794
|
+
const end = findValueEnd(text, j);
|
|
13795
|
+
return [keyStart, end];
|
|
13796
|
+
}
|
|
13797
|
+
}
|
|
13798
|
+
if (text[i2] === '"') {
|
|
13799
|
+
inString = true;
|
|
13800
|
+
i2++;
|
|
13801
|
+
continue;
|
|
13802
|
+
}
|
|
13803
|
+
i2++;
|
|
13804
|
+
}
|
|
13805
|
+
return;
|
|
13806
|
+
}
|
|
13807
|
+
function removeJsoncKey(text, key, searchStart, searchEnd) {
|
|
13808
|
+
const range = findFullKeyRange(text, key, searchStart);
|
|
13809
|
+
if (!range || range[0] >= searchEnd)
|
|
13810
|
+
return;
|
|
13811
|
+
const [keyStart, valueEnd] = range;
|
|
13812
|
+
let removeStart = keyStart;
|
|
13813
|
+
let removeEnd = valueEnd;
|
|
13814
|
+
let b2 = keyStart - 1;
|
|
13815
|
+
while (b2 >= 0 && (text[b2] === " " || text[b2] === "\t" || text[b2] === `
|
|
13816
|
+
` || text[b2] === "\r"))
|
|
13817
|
+
b2--;
|
|
13818
|
+
if (b2 >= 0 && text[b2] === ",") {
|
|
13819
|
+
removeStart = b2;
|
|
13820
|
+
} else {
|
|
13821
|
+
let a2 = valueEnd;
|
|
13822
|
+
while (a2 < text.length && (text[a2] === " " || text[a2] === "\t" || text[a2] === `
|
|
13823
|
+
` || text[a2] === "\r"))
|
|
13824
|
+
a2++;
|
|
13825
|
+
if (a2 < text.length && text[a2] === ",") {
|
|
13826
|
+
removeEnd = a2 + 1;
|
|
13827
|
+
}
|
|
13828
|
+
let lineStart = keyStart - 1;
|
|
13829
|
+
while (lineStart >= 0 && (text[lineStart] === " " || text[lineStart] === "\t"))
|
|
13830
|
+
lineStart--;
|
|
13831
|
+
if (lineStart >= 0 && text[lineStart] === `
|
|
13832
|
+
`) {
|
|
13833
|
+
removeStart = lineStart;
|
|
13834
|
+
}
|
|
13835
|
+
}
|
|
13836
|
+
return text.slice(0, removeStart) + text.slice(removeEnd);
|
|
13837
|
+
}
|
|
13838
|
+
async function removeWranglerVars(appPath, environments, dryRun = false) {
|
|
13839
|
+
const configPath = findWranglerConfig(appPath);
|
|
13840
|
+
if (!configPath) {
|
|
13841
|
+
return { success: true, removedCount: 0 };
|
|
13842
|
+
}
|
|
13843
|
+
let content = await readFile(configPath);
|
|
13844
|
+
const parsed = JSON.parse(stripJsonc(content));
|
|
13845
|
+
const envSection = parsed?.env ?? {};
|
|
13846
|
+
let removedCount = 0;
|
|
13847
|
+
for (const environment of environments) {
|
|
13848
|
+
if (!envSection[environment]?.vars)
|
|
13849
|
+
continue;
|
|
13850
|
+
removedCount++;
|
|
13851
|
+
if (dryRun)
|
|
13852
|
+
continue;
|
|
13853
|
+
const envRange = findKeyRange(content, "env");
|
|
13854
|
+
if (!envRange)
|
|
13855
|
+
continue;
|
|
13856
|
+
const envObjRange = findKeyRange(content, environment, envRange[0]);
|
|
13857
|
+
if (!envObjRange)
|
|
13858
|
+
continue;
|
|
13859
|
+
const result = removeJsoncKey(content, "vars", envObjRange[0], envObjRange[1]);
|
|
13860
|
+
if (result !== undefined) {
|
|
13861
|
+
content = result;
|
|
13862
|
+
}
|
|
13863
|
+
}
|
|
13864
|
+
if (!dryRun && removedCount > 0) {
|
|
13865
|
+
await writeFile(configPath, content);
|
|
13866
|
+
}
|
|
13867
|
+
return { success: true, filePath: configPath, removedCount };
|
|
13868
|
+
}
|
|
13758
13869
|
var init_wrangler = __esm(() => {
|
|
13759
13870
|
init_dist2();
|
|
13760
13871
|
init_process();
|
|
@@ -14410,11 +14521,13 @@ function generateConfigTS(config) {
|
|
|
14410
14521
|
for (const [name, app] of Object.entries(config.apps)) {
|
|
14411
14522
|
lines.push(` ${quoteKey(name)}: {`);
|
|
14412
14523
|
lines.push(` path: ${JSON.stringify(app.path)},`);
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14524
|
+
if (app.workers && Object.keys(app.workers).length > 0) {
|
|
14525
|
+
lines.push(` workers: {`);
|
|
14526
|
+
for (const [env2, worker] of Object.entries(app.workers)) {
|
|
14527
|
+
lines.push(` ${quoteKey(env2)}: ${JSON.stringify(worker)},`);
|
|
14528
|
+
}
|
|
14529
|
+
lines.push(` },`);
|
|
14416
14530
|
}
|
|
14417
|
-
lines.push(` },`);
|
|
14418
14531
|
if (app.secrets?.length) {
|
|
14419
14532
|
lines.push(` secrets: ${JSON.stringify(app.secrets)},`);
|
|
14420
14533
|
}
|
|
@@ -15257,6 +15370,89 @@ var init_encrypt = __esm(() => {
|
|
|
15257
15370
|
});
|
|
15258
15371
|
});
|
|
15259
15372
|
|
|
15373
|
+
// src/commands/clean.ts
|
|
15374
|
+
var exports_clean = {};
|
|
15375
|
+
__export(exports_clean, {
|
|
15376
|
+
default: () => clean_default
|
|
15377
|
+
});
|
|
15378
|
+
import { join as join9, relative as relative4 } from "node:path";
|
|
15379
|
+
import { unlinkSync } from "node:fs";
|
|
15380
|
+
var clean_default;
|
|
15381
|
+
var init_clean = __esm(() => {
|
|
15382
|
+
init_dist();
|
|
15383
|
+
init_dist2();
|
|
15384
|
+
init_config();
|
|
15385
|
+
init_wrangler();
|
|
15386
|
+
init_fs();
|
|
15387
|
+
clean_default = defineCommand({
|
|
15388
|
+
meta: {
|
|
15389
|
+
name: "clean",
|
|
15390
|
+
description: "Remove generated files (.dev.vars, wrangler.jsonc vars)"
|
|
15391
|
+
},
|
|
15392
|
+
args: {
|
|
15393
|
+
"dry-run": {
|
|
15394
|
+
type: "boolean",
|
|
15395
|
+
description: "Show what would be removed without removing",
|
|
15396
|
+
default: false
|
|
15397
|
+
}
|
|
15398
|
+
},
|
|
15399
|
+
async run({ args }) {
|
|
15400
|
+
const rawConfig = await loadConfig();
|
|
15401
|
+
const errors = validateConfig(rawConfig);
|
|
15402
|
+
if (errors.length > 0) {
|
|
15403
|
+
for (const err of errors)
|
|
15404
|
+
consola.error(err);
|
|
15405
|
+
process.exit(1);
|
|
15406
|
+
}
|
|
15407
|
+
const config = resolveConfig(rawConfig);
|
|
15408
|
+
const apps = Object.values(config.apps);
|
|
15409
|
+
if (apps.length === 0) {
|
|
15410
|
+
consola.warn("No apps to process.");
|
|
15411
|
+
return;
|
|
15412
|
+
}
|
|
15413
|
+
const dryRun = args["dry-run"];
|
|
15414
|
+
let removedFiles = 0;
|
|
15415
|
+
let removedVars = 0;
|
|
15416
|
+
for (const app of apps) {
|
|
15417
|
+
for (const devFileName of app.devFiles) {
|
|
15418
|
+
const filePath = join9(app.absolutePath, devFileName);
|
|
15419
|
+
if (!fileExists(filePath))
|
|
15420
|
+
continue;
|
|
15421
|
+
const rel = relative4(config.projectRoot, filePath);
|
|
15422
|
+
if (dryRun) {
|
|
15423
|
+
consola.log(` Would remove ${rel}`);
|
|
15424
|
+
} else {
|
|
15425
|
+
unlinkSync(filePath);
|
|
15426
|
+
consola.log(` Removed ${rel}`);
|
|
15427
|
+
}
|
|
15428
|
+
removedFiles++;
|
|
15429
|
+
}
|
|
15430
|
+
const result = await removeWranglerVars(app.absolutePath, config.environments, dryRun);
|
|
15431
|
+
if (result.success && result.removedCount > 0) {
|
|
15432
|
+
const rel = relative4(config.projectRoot, result.filePath);
|
|
15433
|
+
if (dryRun) {
|
|
15434
|
+
consola.log(` Would remove ${result.removedCount} vars section(s) from ${rel}`);
|
|
15435
|
+
} else {
|
|
15436
|
+
consola.log(` Removed ${result.removedCount} vars section(s) from ${rel}`);
|
|
15437
|
+
}
|
|
15438
|
+
removedVars += result.removedCount;
|
|
15439
|
+
}
|
|
15440
|
+
}
|
|
15441
|
+
if (removedFiles === 0 && removedVars === 0) {
|
|
15442
|
+
consola.info("Nothing to clean.");
|
|
15443
|
+
return;
|
|
15444
|
+
}
|
|
15445
|
+
const action = dryRun ? "Would remove" : "Removed";
|
|
15446
|
+
const parts = [];
|
|
15447
|
+
if (removedFiles > 0)
|
|
15448
|
+
parts.push(`${removedFiles} file(s)`);
|
|
15449
|
+
if (removedVars > 0)
|
|
15450
|
+
parts.push(`${removedVars} vars section(s)`);
|
|
15451
|
+
consola.success(`${action} ${parts.join(", ")}.`);
|
|
15452
|
+
}
|
|
15453
|
+
});
|
|
15454
|
+
});
|
|
15455
|
+
|
|
15260
15456
|
// src/index.ts
|
|
15261
15457
|
init_dist();
|
|
15262
15458
|
var main = defineCommand({
|
|
@@ -15275,7 +15471,8 @@ var main = defineCommand({
|
|
|
15275
15471
|
normalize: () => Promise.resolve().then(() => (init_normalize(), exports_normalize)).then((m2) => m2.default),
|
|
15276
15472
|
merge: () => Promise.resolve().then(() => (init_merge(), exports_merge)).then((m2) => m2.default),
|
|
15277
15473
|
list: () => Promise.resolve().then(() => (init_list(), exports_list)).then((m2) => m2.default),
|
|
15278
|
-
encrypt: () => Promise.resolve().then(() => (init_encrypt(), exports_encrypt)).then((m2) => m2.default)
|
|
15474
|
+
encrypt: () => Promise.resolve().then(() => (init_encrypt(), exports_encrypt)).then((m2) => m2.default),
|
|
15475
|
+
clean: () => Promise.resolve().then(() => (init_clean(), exports_clean)).then((m2) => m2.default)
|
|
15279
15476
|
}
|
|
15280
15477
|
});
|
|
15281
15478
|
runMain(main);
|
package/package.json
CHANGED
package/src/types/config.ts
CHANGED
|
@@ -35,8 +35,8 @@ export interface EnvSyncConfig {
|
|
|
35
35
|
export interface AppConfig {
|
|
36
36
|
/** Path to app directory relative to project root */
|
|
37
37
|
path: string;
|
|
38
|
-
/** Cloudflare Worker names per environment */
|
|
39
|
-
workers
|
|
38
|
+
/** Cloudflare Worker names per environment (omit for non-worker apps) */
|
|
39
|
+
workers?: Record<string, string>;
|
|
40
40
|
/** Secret keys for this app (pushed via wrangler secret) */
|
|
41
41
|
secrets?: string[];
|
|
42
42
|
/** Var keys for this app (non-secret env vars) */
|