@itznexus/itznexus-cli 1.120.0 → 1.122.0

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.
@@ -0,0 +1,110 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { api } from "./api.js";
4
+ import { gitStatus } from "./project-context.js";
5
+ export function fetchRenderedEnvFiles(ref) {
6
+ return api.get(`/projects/${encodeURIComponent(ref)}/env-vars/rendered`);
7
+ }
8
+ // .env.local uses a "#" marker line instead of the HTML comment: it must stay
9
+ // a parseable dotenv file. Only marked files are overwritten or deleted, so a
10
+ // hand-written .env.local is never clobbered without --force.
11
+ const ENV_FILE_NAME = ".env.local";
12
+ const ENV_MANAGED_MARKER = "# Nexus-managed";
13
+ const ENV_MANAGED_HEADER = "# Nexus-managed. Edit in Nexus (project Agents tab), not here: `itznexus project sync` overwrites this file.";
14
+ function isEnvManaged(filePath) {
15
+ return fs
16
+ .readFileSync(filePath, "utf-8")
17
+ .trimStart()
18
+ .startsWith(ENV_MANAGED_MARKER);
19
+ }
20
+ function envTarget(cwd, repo) {
21
+ return path.join(cwd, repo, ENV_FILE_NAME);
22
+ }
23
+ /**
24
+ * Env files that already exist on disk but were not written by Nexus.
25
+ * Callers fail fast on these before doing any other work, unless --force.
26
+ */
27
+ export function findEnvConflicts(cwd, envFiles) {
28
+ return envFiles
29
+ .map((f) => `${f.repo}/${ENV_FILE_NAME}`)
30
+ .filter((rel) => {
31
+ const target = path.join(cwd, ...rel.split("/"));
32
+ return fs.existsSync(target) && !isEnvManaged(target);
33
+ });
34
+ }
35
+ // The instruction pattern *.local.* does not match .env.local (nothing follows
36
+ // the last dot), so the file needs its own entry. check-ignore runs first:
37
+ // most repos already ignore it via their own .env* rules, and a redundant
38
+ // entry would be committed noise.
39
+ function ensureEnvIgnored(repoDir) {
40
+ if (gitStatus(["check-ignore", "-q", ENV_FILE_NAME], repoDir) === 0) {
41
+ return false;
42
+ }
43
+ const gitignorePath = path.join(repoDir, ".gitignore");
44
+ const current = fs.existsSync(gitignorePath)
45
+ ? fs.readFileSync(gitignorePath, "utf-8")
46
+ : "";
47
+ const suffix = current.length === 0 || current.endsWith("\n") ? "" : "\n";
48
+ fs.writeFileSync(gitignorePath, `${current}${suffix}${ENV_FILE_NAME}\n`);
49
+ return true;
50
+ }
51
+ /**
52
+ * Writes every rendered env file as <repo>/.env.local, under the same git
53
+ * safety rules as nested instruction files: provably gitignored before
54
+ * writing, never overwriting a tracked file. Conflicts (existing unmanaged
55
+ * files) are the caller's job via findEnvConflicts.
56
+ */
57
+ export function syncEnvFiles(cwd, envFiles) {
58
+ const results = [];
59
+ for (const file of envFiles) {
60
+ const rel = `${file.repo}/${ENV_FILE_NAME}`;
61
+ const repoDir = path.join(cwd, file.repo);
62
+ const push = (status, extra) => results.push({ path: rel, status, gitignoreUpdated: false, ...extra });
63
+ if (!fs.existsSync(repoDir)) {
64
+ push("skipped-no-folder");
65
+ continue;
66
+ }
67
+ let gitignoreUpdated = false;
68
+ if (fs.existsSync(path.join(repoDir, ".git"))) {
69
+ if (gitStatus(["ls-files", "--error-unmatch", ENV_FILE_NAME], repoDir) === 0) {
70
+ push("error", {
71
+ error: `${ENV_FILE_NAME} is tracked by git; run \`git rm --cached ${ENV_FILE_NAME}\` in ${file.repo} and commit before syncing`,
72
+ });
73
+ continue;
74
+ }
75
+ gitignoreUpdated = ensureEnvIgnored(repoDir);
76
+ if (gitStatus(["check-ignore", "-q", ENV_FILE_NAME], repoDir) !== 0) {
77
+ push("error", {
78
+ gitignoreUpdated,
79
+ error: `${ENV_FILE_NAME} is still not gitignored after adding ${ENV_FILE_NAME} (negated elsewhere?); refusing to write`,
80
+ });
81
+ continue;
82
+ }
83
+ }
84
+ fs.writeFileSync(envTarget(cwd, file.repo), `${ENV_MANAGED_HEADER}\n${file.content}\n`);
85
+ push("written", { gitignoreUpdated });
86
+ }
87
+ return results;
88
+ }
89
+ /**
90
+ * Deletes Nexus-managed .env.local files in repos whose env disappeared from
91
+ * Nexus. Unmanaged files are never touched. Returns the deleted paths,
92
+ * relative to the project folder.
93
+ */
94
+ export function cleanupStaleEnvFiles(cwd, envFiles, repoNames) {
95
+ const expected = new Set(envFiles.map((f) => f.repo));
96
+ const removed = [];
97
+ for (const repoName of repoNames) {
98
+ if (expected.has(repoName))
99
+ continue;
100
+ const target = envTarget(cwd, repoName);
101
+ if (!fs.existsSync(target))
102
+ continue;
103
+ if (!isEnvManaged(target))
104
+ continue;
105
+ fs.rmSync(target);
106
+ removed.push(`${repoName}/${ENV_FILE_NAME}`);
107
+ }
108
+ return removed;
109
+ }
110
+ //# sourceMappingURL=project-env-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-env-files.js","sourceRoot":"","sources":["../../src/lib/project-env-files.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itznexus/itznexus-cli",
3
- "version": "1.120.0",
3
+ "version": "1.122.0",
4
4
  "description": "ITzNexus CLI: operational commands for ITzWorking",
5
5
  "type": "module",
6
6
  "publishConfig": {