@confiqure/cli 0.1.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,227 @@
1
+ import { confirm } from "@inquirer/prompts";
2
+ import chalk from "chalk";
3
+ import { requireCredentials } from "../credentials.js";
4
+ import { loadConfig } from "../config.js";
5
+ import { scanProject } from "../scan.js";
6
+ import { diffAgainstRegistry, renderDiff } from "../diff.js";
7
+ import { getRegistry, postUpload, getPushStatus, ApiError, } from "../api.js";
8
+ import { gitDirtyInScanPaths, gitHashObject, gitHeadSha, gitRef, } from "../git.js";
9
+ const WATCH_TIMEOUT_MS = 30_000;
10
+ const WATCH_INTERVAL_MS = 1000;
11
+ export function registerPush(program) {
12
+ program
13
+ .command("push")
14
+ .description("Push @Confiqure-annotated classes to your workspace")
15
+ .option("-y, --yes", "skip the confirmation prompt")
16
+ .option("--allow-dirty", "upload working-tree (uncommitted) content; backend gitVersion will not match any committed SHA")
17
+ .option("--no-watch", "don't poll for playbook generation completion after upload")
18
+ .action(async (opts) => {
19
+ const cwd = process.cwd();
20
+ const creds = await requireCredentials();
21
+ const config = await loadConfig(cwd);
22
+ // ── 1. Scan + diff ───────────────────────────────────────────────────
23
+ const scan = await scanProject(cwd, config);
24
+ console.log(chalk.dim(`Scanned ${scan.allFiles.size} files; ${scan.annotated.length} @Confiqure root${scan.annotated.length === 1 ? "" : "s"}.`));
25
+ // Show the class tree per root so the user can see exactly which files
26
+ // we'll ship and why — covers the case the keyword scan used to miss
27
+ // (nested types referenced from a root but never annotated themselves).
28
+ console.log();
29
+ console.log(renderTrees(scan));
30
+ const registry = await getRegistry(creds);
31
+ const diff = diffAgainstRegistry(scan.annotated, registry);
32
+ console.log();
33
+ console.log(renderDiff(diff, {
34
+ allScannedPaths: Array.from(scan.reachableFiles),
35
+ annotatedPaths: scan.annotated.map((c) => c.filePath),
36
+ }));
37
+ if (diff.changes.length === 0) {
38
+ return;
39
+ }
40
+ // ── 2. Git state check ───────────────────────────────────────────────
41
+ const dirty = await gitDirtyInScanPaths(cwd, config.scanPaths);
42
+ if (dirty.length > 0) {
43
+ if (!opts.allowDirty) {
44
+ console.log();
45
+ console.log(chalk.red("✗"), chalk.bold(`Push blocked. ${dirty.length} file${dirty.length === 1 ? "" : "s"} in scanPaths ${dirty.length === 1 ? "has" : "have"} uncommitted changes:`));
46
+ console.log();
47
+ for (const f of dirty) {
48
+ console.log(` ${chalk.yellow(f.status)} ${f.path}`);
49
+ }
50
+ console.log();
51
+ console.log("Commit them (recommended), or re-run with " + chalk.cyan("--allow-dirty") + " to upload working-tree content.");
52
+ process.exitCode = 1;
53
+ return;
54
+ }
55
+ // --allow-dirty: warn loudly and proceed.
56
+ printDirtyWarning(dirty);
57
+ }
58
+ // ── 3. Confirm + upload ──────────────────────────────────────────────
59
+ if (!opts.yes) {
60
+ const ok = await confirm({
61
+ message: `Upload ${diff.changes.length} change${diff.changes.length === 1 ? "" : "s"}?`,
62
+ default: true,
63
+ });
64
+ if (!ok) {
65
+ console.log(chalk.yellow("Aborted."));
66
+ return;
67
+ }
68
+ }
69
+ const headSha = await gitHeadSha(cwd);
70
+ const ref = await gitRef(cwd);
71
+ // Upload only files reachable from an annotated root — every file in
72
+ // the manifest needs a stable git SHA so the backend can pin a version
73
+ // to commit content. Computing SHAs is one shell-out per file, so
74
+ // limiting the set keeps push snappy on large repos.
75
+ const uploadPaths = Array.from(scan.reachableFiles).sort();
76
+ const files = [];
77
+ for (const path of uploadPaths) {
78
+ const sha = await gitHashObject(path, cwd).catch(() => "");
79
+ files.push({ path, sha });
80
+ }
81
+ const shaCount = files.filter((f) => f.sha !== "").length;
82
+ console.log(chalk.dim(`Git SHAs computed for ${shaCount}/${files.length} files.`));
83
+ const manifest = {
84
+ workspaceKey: creds.workspaceKey,
85
+ gitRef: ref,
86
+ headSha,
87
+ language: scan.primaryLanguage,
88
+ changes: diff.changes,
89
+ files,
90
+ };
91
+ // Ship only the files actually referenced by an annotated root.
92
+ const uploadFiles = new Map();
93
+ for (const p of uploadPaths) {
94
+ const content = scan.allFiles.get(p);
95
+ if (content != null)
96
+ uploadFiles.set(p, content);
97
+ }
98
+ const result = await postUpload(creds, manifest, uploadFiles);
99
+ console.log();
100
+ console.log(chalk.bold(`Uploaded: ${result.accepted}/${result.totalClasses} accepted, ${result.rejected} rejected.`));
101
+ for (const item of result.items) {
102
+ const icon = item.status === "ACCEPTED"
103
+ ? chalk.green("✓")
104
+ : item.status === "DELETED"
105
+ ? chalk.gray("−")
106
+ : chalk.red("✗");
107
+ const tail = item.error ? chalk.red(` — ${item.error}`) : "";
108
+ console.log(` ${icon} ${item.className.padEnd(28)} ${item.status}${tail}`);
109
+ }
110
+ // ── 4. Optional watch loop ───────────────────────────────────────────
111
+ const acceptedForWatch = result.items.filter((i) => i.status === "ACCEPTED" && i.pushHistoryId != null);
112
+ if (acceptedForWatch.length === 0) {
113
+ if (result.rejected > 0)
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+ if (opts.watch === false) {
118
+ console.log();
119
+ console.log(chalk.dim("Playbook generation continues in the background — view status in the dashboard."));
120
+ return;
121
+ }
122
+ console.log();
123
+ console.log(chalk.dim("Waiting for playbook generation…"));
124
+ const failures = await watchGeneration(creds, acceptedForWatch);
125
+ if (failures > 0 || result.rejected > 0) {
126
+ process.exitCode = 1;
127
+ }
128
+ });
129
+ }
130
+ /**
131
+ * Render the per-root class tree, e.g.
132
+ *
133
+ * ⏵ Found 1 @Confiqure root: NotificationPreferences
134
+ * ├─ NotificationPreferences.java root, 9 fields
135
+ * ├─ EmailPreferences.java referenced
136
+ * ├─ … (8 more)
137
+ *
138
+ * The point is to surface, before the upload confirm, exactly which files
139
+ * we're about to ship and which classes the reachability walk traversed —
140
+ * so a forgotten `@confiqure` doc-tag on a nested type is visible at a
141
+ * glance rather than silently dropped.
142
+ */
143
+ function renderTrees(scan) {
144
+ const lines = [];
145
+ if (scan.annotated.length === 0) {
146
+ lines.push(chalk.yellow("⚠ No @Confiqure roots found in scanPaths."));
147
+ return lines.join("\n");
148
+ }
149
+ for (const root of scan.annotated) {
150
+ const lang = root.language === "java" ? "" : chalk.dim(` (${root.language})`);
151
+ lines.push(`${chalk.cyan("⏵")} Root: ${chalk.bold(root.className)}${lang} — ${root.relatedFiles.length} reachable file${root.relatedFiles.length === 1 ? "" : "s"}`);
152
+ if (root.subsumedConfiqureClasses.length > 0) {
153
+ lines.push(chalk.yellow(` ⚠ Nested @Confiqure classes subsumed under this root: ${root.subsumedConfiqureClasses.join(", ")}`));
154
+ }
155
+ const sortedFiles = [...root.relatedFiles].sort();
156
+ const lastIdx = sortedFiles.length - 1;
157
+ for (let i = 0; i < sortedFiles.length; i++) {
158
+ const file = sortedFiles[i];
159
+ const isRoot = file === root.filePath;
160
+ const prefix = i === lastIdx ? "└─" : "├─";
161
+ const label = isRoot ? chalk.bold("root") : chalk.dim("referenced");
162
+ lines.push(` ${prefix} ${file} ${label}`);
163
+ }
164
+ }
165
+ return lines.join("\n");
166
+ }
167
+ function printDirtyWarning(dirty) {
168
+ console.log();
169
+ console.log(chalk.yellow("⚠"), chalk.bold("--allow-dirty: uploading working-tree content not in git history."));
170
+ console.log(chalk.yellow(" Backend's gitVersion will not match any commit you can `git checkout`."));
171
+ console.log();
172
+ for (const f of dirty) {
173
+ console.log(` ${chalk.yellow(f.status)} ${f.path}`);
174
+ }
175
+ console.log();
176
+ }
177
+ /**
178
+ * Poll the backend's per-push status endpoint until each accepted class
179
+ * reports `playbookReady`, or the timeout fires. Returns the count of
180
+ * classes that did NOT reach ready before the deadline.
181
+ */
182
+ async function watchGeneration(creds, items) {
183
+ const startedAt = Date.now();
184
+ const pending = new Map();
185
+ for (const item of items) {
186
+ if (item.pushHistoryId == null)
187
+ continue;
188
+ pending.set(item.pushHistoryId, { className: item.className, startedAt });
189
+ }
190
+ let failures = 0;
191
+ while (pending.size > 0) {
192
+ if (Date.now() - startedAt > WATCH_TIMEOUT_MS) {
193
+ for (const [, info] of pending) {
194
+ console.log(` ${chalk.yellow("⚠")} ${info.className.padEnd(28)} still generating after ${(WATCH_TIMEOUT_MS / 1000).toFixed(0)}s — check the dashboard`);
195
+ failures++;
196
+ }
197
+ break;
198
+ }
199
+ await sleep(WATCH_INTERVAL_MS);
200
+ const doneIds = [];
201
+ for (const [pushHistoryId, info] of pending) {
202
+ try {
203
+ const status = await getPushStatus(creds, pushHistoryId);
204
+ if (status.playbookReady) {
205
+ const elapsed = ((Date.now() - info.startedAt) / 1000).toFixed(1);
206
+ console.log(` ${chalk.green("✓")} ${info.className.padEnd(28)} ready (${elapsed}s)`);
207
+ doneIds.push(pushHistoryId);
208
+ }
209
+ }
210
+ catch (e) {
211
+ if (e instanceof ApiError && e.status === 404) {
212
+ console.log(` ${chalk.red("✗")} ${info.className.padEnd(28)} not found (push deleted?)`);
213
+ doneIds.push(pushHistoryId);
214
+ failures++;
215
+ }
216
+ // Transient errors: silently retry on next tick.
217
+ }
218
+ }
219
+ for (const id of doneIds)
220
+ pending.delete(id);
221
+ }
222
+ return failures;
223
+ }
224
+ function sleep(ms) {
225
+ return new Promise((resolve) => setTimeout(resolve, ms));
226
+ }
227
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import chalk from "chalk";
2
+ import { credentialsPath, loadCredentials } from "../credentials.js";
3
+ import { gitStatus } from "../git.js";
4
+ import { loadConfig } from "../config.js";
5
+ export function registerStatus(program) {
6
+ program
7
+ .command("status")
8
+ .description("Show credential state, workspace, and git status")
9
+ .action(async () => {
10
+ const creds = await loadCredentials();
11
+ console.log(chalk.bold("Credentials"));
12
+ if (creds) {
13
+ console.log(` apiBase: ${creds.apiBase}`);
14
+ console.log(` workspaceKey: ${creds.workspaceKey}`);
15
+ console.log(` token: ${creds.token.slice(0, 12)}…`);
16
+ console.log(` file: ${credentialsPath()}`);
17
+ }
18
+ else {
19
+ console.log(chalk.yellow(` not configured — run \`confiqure login\``));
20
+ }
21
+ console.log();
22
+ console.log(chalk.bold("Project config"));
23
+ try {
24
+ const config = await loadConfig(process.cwd());
25
+ console.log(` scanPaths: ${config.scanPaths.join(", ")}`);
26
+ console.log(` languages: ${Object.keys(config.languages).join(", ")}`);
27
+ }
28
+ catch (e) {
29
+ console.log(chalk.dim(` (could not read confiqure.config.json: ${e.message})`));
30
+ }
31
+ console.log();
32
+ console.log(chalk.bold("Git"));
33
+ try {
34
+ const g = await gitStatus(process.cwd());
35
+ console.log(` branch: ${g.branch}`);
36
+ console.log(` dirty: ${g.isDirty ? chalk.yellow("yes") : "no"}`);
37
+ console.log(` upstream: ${g.upstreamConfigured ? "configured" : chalk.dim("(none)")}`);
38
+ if (g.upstreamConfigured) {
39
+ console.log(` ahead: ${g.aheadOfUpstream ? chalk.yellow("yes") : "no"}`);
40
+ }
41
+ }
42
+ catch (e) {
43
+ console.log(chalk.dim(` (not a git repo: ${e.message})`));
44
+ }
45
+ });
46
+ }
47
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import chalk from "chalk";
2
+ import { readFile } from "node:fs/promises";
3
+ import { requireCredentials } from "../credentials.js";
4
+ import { listTools, upsertTool, deleteTool, ApiError } from "../api.js";
5
+ export function registerTools(program) {
6
+ const tools = program
7
+ .command("tools")
8
+ .description("List, register, or remove workspace tools (URL + instructions)");
9
+ tools
10
+ .command("list")
11
+ .description("List tools registered in the current workspace")
12
+ .action(async () => {
13
+ const creds = await requireCredentials();
14
+ const items = await listTools(creds);
15
+ if (items.length === 0) {
16
+ console.log(chalk.dim("(no tools registered)"));
17
+ console.log(chalk.dim("Add one with: ") +
18
+ chalk.cyan("confiqure tools set <name> --url <url> --instructions \"...\""));
19
+ return;
20
+ }
21
+ for (const t of items) {
22
+ const firstLine = (t.instructions ?? "").split(/\r?\n/)[0] ?? "";
23
+ console.log(`${chalk.cyan(t.name.padEnd(24))} ${chalk.dim(t.url)}`);
24
+ if (firstLine) {
25
+ console.log(` ${chalk.dim(firstLine)}`);
26
+ }
27
+ }
28
+ });
29
+ tools
30
+ .command("set <name>")
31
+ .description("Create or update a tool. Provide --url and (optionally) instructions.")
32
+ .requiredOption("--url <url>", "Tool callback URL the backend will POST to")
33
+ .option("--instructions <text>", "Free-text guidance for the AI: what the tool does, when to invoke it")
34
+ .option("--instructions-file <path>", "Read instructions from a file (e.g. instructions.md) — overrides --instructions")
35
+ .action(async (name, opts) => {
36
+ const creds = await requireCredentials();
37
+ let instructions = opts.instructions ?? null;
38
+ if (opts.instructionsFile) {
39
+ instructions = (await readFile(opts.instructionsFile, "utf8")).trim();
40
+ }
41
+ try {
42
+ const saved = await upsertTool(creds, name, opts.url, instructions);
43
+ console.log(chalk.green("✓"), `${saved.name} → ${saved.url}`);
44
+ if (saved.instructions) {
45
+ const first = saved.instructions.split(/\r?\n/)[0] ?? "";
46
+ console.log(chalk.dim(` ${first}`));
47
+ }
48
+ }
49
+ catch (e) {
50
+ if (e instanceof ApiError) {
51
+ console.error(chalk.red("✗"), `set ${name} failed (${e.status}): ${e.message}`);
52
+ process.exit(1);
53
+ }
54
+ throw e;
55
+ }
56
+ });
57
+ tools
58
+ .command("delete <name>")
59
+ .description("Remove a tool from this workspace")
60
+ .action(async (name) => {
61
+ const creds = await requireCredentials();
62
+ try {
63
+ await deleteTool(creds, name);
64
+ console.log(chalk.green("✓"), `removed ${name}`);
65
+ }
66
+ catch (e) {
67
+ if (e instanceof ApiError) {
68
+ console.error(chalk.red("✗"), `delete ${name} failed (${e.status}): ${e.message}`);
69
+ process.exit(1);
70
+ }
71
+ throw e;
72
+ }
73
+ });
74
+ }
75
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/commands/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import chalk from "chalk";
2
+ import { requireCredentials } from "../credentials.js";
3
+ import { getWorkspace, updateWorkspace, ApiError } from "../api.js";
4
+ export function registerWorkspace(program) {
5
+ const ws = program
6
+ .command("workspace")
7
+ .description("View or update workspace-level settings (e.g. default callback URL)");
8
+ ws.command("get")
9
+ .description("Show workspace settings")
10
+ .action(async () => {
11
+ const creds = await requireCredentials();
12
+ try {
13
+ const data = await getWorkspace(creds);
14
+ console.log(`${chalk.bold("workspace")} ${data.urlKey} (${data.name})`);
15
+ console.log(` defaultCallbackUrl: ${data.defaultCallbackUrl ?? chalk.dim("(unset)")}`);
16
+ }
17
+ catch (e) {
18
+ if (e instanceof ApiError) {
19
+ console.error(chalk.red("✗"), `get failed (${e.status}): ${e.message}`);
20
+ process.exit(1);
21
+ }
22
+ throw e;
23
+ }
24
+ });
25
+ ws.command("set")
26
+ .description("Update workspace settings. Pass --default-callback-url '' to clear.")
27
+ .option("--default-callback-url <url>", "Fallback URL used when @Confiqure(callback=\"\") is blank on a class")
28
+ .action(async (opts) => {
29
+ const creds = await requireCredentials();
30
+ if (opts.defaultCallbackUrl === undefined) {
31
+ console.log(chalk.yellow("Nothing to update. Pass --default-callback-url <url>."));
32
+ return;
33
+ }
34
+ try {
35
+ const saved = await updateWorkspace(creds, {
36
+ defaultCallbackUrl: opts.defaultCallbackUrl,
37
+ });
38
+ console.log(chalk.green("✓"), `workspace ${saved.urlKey}`);
39
+ console.log(` defaultCallbackUrl: ${saved.defaultCallbackUrl ?? chalk.dim("(unset)")}`);
40
+ }
41
+ catch (e) {
42
+ if (e instanceof ApiError) {
43
+ console.error(chalk.red("✗"), `set failed (${e.status}): ${e.message}`);
44
+ process.exit(1);
45
+ }
46
+ throw e;
47
+ }
48
+ });
49
+ }
50
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/commands/workspace.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEpE,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,EAAE,GAAG,OAAO;SACf,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,qEAAqE,CAAC,CAAC;IAEtF,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,qEAAqE,CAAC;SAClF,MAAM,CACL,8BAA8B,EAC9B,sEAAsE,CACvE;SACA,MAAM,CAAC,KAAK,EAAE,IAAqC,EAAE,EAAE;QACtD,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,uDAAuD,CAAC,CAAC,CAAC;YACnF,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE;gBACzC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;aAC5C,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,53 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ export const CONFIG_FILE = "confiqure.config.json";
5
+ /**
6
+ * Default scan + token-pattern config covering the 9 V1 annotation-native
7
+ * languages. Swift V1 uses `Confiqurable` protocol (macro support deferred).
8
+ */
9
+ export const DEFAULT_CONFIG = {
10
+ scanPaths: ["src/**", "lib/**", "app/**"],
11
+ ignore: [
12
+ "node_modules",
13
+ ".git",
14
+ "target",
15
+ "build",
16
+ "dist",
17
+ ".nuxt",
18
+ ".output",
19
+ ".venv",
20
+ "__pycache__",
21
+ "bin",
22
+ "obj",
23
+ ],
24
+ languages: {
25
+ java: { extensions: [".java"], tokenPattern: "@Confiqure" },
26
+ kotlin: { extensions: [".kt"], tokenPattern: "@Confiqure" },
27
+ scala: { extensions: [".scala"], tokenPattern: "@Confiqure" },
28
+ python: { extensions: [".py"], tokenPattern: "@Confiqure" },
29
+ typescript: { extensions: [".ts", ".tsx", ".js", ".jsx"], tokenPattern: "@Confiqure" },
30
+ csharp: { extensions: [".cs"], tokenPattern: "[Confiqure" },
31
+ rust: { extensions: [".rs"], tokenPattern: "#[confiqure" },
32
+ php: { extensions: [".php"], tokenPattern: "#[Confiqure" },
33
+ swift: { extensions: [".swift"], tokenPattern: "Confiqurable" },
34
+ },
35
+ };
36
+ export async function loadConfig(cwd) {
37
+ const path = join(cwd, CONFIG_FILE);
38
+ if (!existsSync(path)) {
39
+ return DEFAULT_CONFIG;
40
+ }
41
+ const raw = await readFile(path, "utf8");
42
+ const parsed = JSON.parse(raw);
43
+ return {
44
+ scanPaths: parsed.scanPaths ?? DEFAULT_CONFIG.scanPaths,
45
+ ignore: parsed.ignore ?? DEFAULT_CONFIG.ignore,
46
+ languages: parsed.languages ?? DEFAULT_CONFIG.languages,
47
+ };
48
+ }
49
+ export async function saveConfig(cwd, config) {
50
+ const path = join(cwd, CONFIG_FILE);
51
+ await writeFile(path, JSON.stringify(config, null, 2), { encoding: "utf8" });
52
+ }
53
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAajC,MAAM,CAAC,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACzC,MAAM,EAAE;QACN,cAAc;QACd,MAAM;QACN,QAAQ;QACR,OAAO;QACP,MAAM;QACN,OAAO;QACP,SAAS;QACT,OAAO;QACP,aAAa;QACb,KAAK;QACL,KAAK;KACN;IACD,SAAS,EAAE;QACT,IAAI,EAAQ,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAI,YAAY,EAAE,YAAY,EAAE;QACnE,MAAM,EAAM,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAM,YAAY,EAAE,YAAY,EAAE;QACnE,KAAK,EAAO,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAG,YAAY,EAAE,YAAY,EAAE;QACnE,MAAM,EAAM,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAM,YAAY,EAAE,YAAY,EAAE;QACnE,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE;QACtF,MAAM,EAAM,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAM,YAAY,EAAE,YAAY,EAAE;QACnE,IAAI,EAAQ,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAM,YAAY,EAAE,aAAa,EAAE;QACpE,GAAG,EAAS,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,EAAK,YAAY,EAAE,aAAa,EAAE;QACpE,KAAK,EAAO,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAG,YAAY,EAAE,cAAc,EAAE;KACtE;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC;IACzD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,cAAc,CAAC,SAAS;QACvD,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM;QAC9C,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,cAAc,CAAC,SAAS;KACxD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,MAAqB;IACjE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACpC,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { homedir, platform } from "node:os";
2
+ import { join, dirname } from "node:path";
3
+ import { mkdir, readFile, writeFile, chmod } from "node:fs/promises";
4
+ import { existsSync } from "node:fs";
5
+ const DEFAULT_API_BASE = "https://api.confiqure.ai";
6
+ export function credentialsPath() {
7
+ if (platform() === "win32") {
8
+ const base = process.env.APPDATA ?? homedir();
9
+ return join(base, "confiqure", "credentials");
10
+ }
11
+ return join(homedir(), ".confiqure", "credentials");
12
+ }
13
+ /** Env vars override the file — handy for CI. */
14
+ function envCredentials() {
15
+ const token = process.env.CONFIQURE_API_KEY;
16
+ const workspaceKey = process.env.CONFIQURE_WORKSPACE_KEY;
17
+ if (!token || !workspaceKey)
18
+ return null;
19
+ return {
20
+ apiBase: process.env.CONFIQURE_API_BASE ?? DEFAULT_API_BASE,
21
+ workspaceKey,
22
+ token,
23
+ };
24
+ }
25
+ export async function loadCredentials() {
26
+ const fromEnv = envCredentials();
27
+ if (fromEnv)
28
+ return fromEnv;
29
+ const path = credentialsPath();
30
+ if (!existsSync(path))
31
+ return null;
32
+ try {
33
+ const raw = await readFile(path, "utf8");
34
+ const parsed = JSON.parse(raw);
35
+ if (!parsed.token || !parsed.workspaceKey)
36
+ return null;
37
+ return {
38
+ apiBase: parsed.apiBase ?? DEFAULT_API_BASE,
39
+ workspaceKey: parsed.workspaceKey,
40
+ token: parsed.token,
41
+ };
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ export async function saveCredentials(creds) {
48
+ const path = credentialsPath();
49
+ await mkdir(dirname(path), { recursive: true });
50
+ await writeFile(path, JSON.stringify(creds, null, 2), { encoding: "utf8" });
51
+ if (platform() !== "win32") {
52
+ try {
53
+ await chmod(path, 0o600);
54
+ }
55
+ catch {
56
+ /* best-effort */
57
+ }
58
+ }
59
+ }
60
+ export async function requireCredentials() {
61
+ const creds = await loadCredentials();
62
+ if (!creds) {
63
+ throw new Error(`Not logged in. Run \`confiqure login\` to set up credentials at ${credentialsPath()}.`);
64
+ }
65
+ return creds;
66
+ }
67
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}