intentdocs 0.8.0 → 0.10.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.
Files changed (34) hide show
  1. package/README.md +2 -1
  2. package/bin/intentdocs.js +2 -0
  3. package/dist/{chunk-4OWPN2RE.js → chunk-5USVG4DW.js} +24 -43
  4. package/dist/{chunk-IKF3ZLHK.js → chunk-EEKEF2FD.js} +65 -101
  5. package/dist/chunk-HEHHSSUM.js +43 -0
  6. package/dist/chunk-IDNUBI2P.js +317 -0
  7. package/dist/chunk-LQTPZL2Y.js +15 -0
  8. package/dist/chunk-LXQXJULN.js +105 -0
  9. package/dist/{chunk-6FGYJ3W2.js → chunk-NFIXRIHM.js} +43 -4
  10. package/dist/{chunk-ICOMMHKG.js → chunk-UF535HZL.js} +12 -1
  11. package/dist/{chunk-ITQUQYWB.js → chunk-UR73WX5I.js} +1 -1
  12. package/dist/chunk-UYTVTYNB.js +11 -0
  13. package/dist/{chunk-WPVDURTJ.js → chunk-WRRUCCVZ.js} +27 -3
  14. package/dist/chunk-YUW3W43S.js +170 -0
  15. package/dist/ci-LBOCMRKZ.js +11 -0
  16. package/dist/{complexity-NSSYVT54.js → complexity-ZOB3BPVD.js} +12 -7
  17. package/dist/{import-prd-CKV3R67G.js → import-prd-MJUCIMHX.js} +13 -11
  18. package/dist/index.js +420 -179
  19. package/dist/{keys-EDWET3WG.js → keys-5PA3D6CX.js} +8 -7
  20. package/dist/log-EVLWM64C.js +206 -0
  21. package/dist/{map-extract-I3AACTGL.js → map-extract-W6WJLVOF.js} +2 -1
  22. package/dist/{map-import-IYUMRASO.js → map-import-LL4AIAQE.js} +12 -10
  23. package/dist/{map-schema-JVL3O2TJ.js → map-schema-6GL2UKZQ.js} +1 -1
  24. package/dist/projects-F7GMH66U.js +37 -0
  25. package/dist/{prompt-WAWCRGHN.js → prompt-GOAFIKBZ.js} +3 -1
  26. package/dist/{research-6SXJ37TI.js → research-4ASCZSZN.js} +12 -10
  27. package/dist/scope-S3LZZ3KB.js +11 -0
  28. package/dist/setup-YLUPBLK6.js +14 -0
  29. package/package.json +4 -2
  30. package/dist/chunk-6XKB6RTU.js +0 -123
  31. package/dist/chunk-PCNDP5SX.js +0 -34
  32. package/dist/log-TT2UCJP7.js +0 -94
  33. package/dist/scope-OGKQ472D.js +0 -10
  34. package/dist/setup-SOI2HQAL.js +0 -11
@@ -1,15 +1,16 @@
1
1
  import {
2
2
  ask,
3
3
  closePrompt
4
- } from "./chunk-WPVDURTJ.js";
4
+ } from "./chunk-WRRUCCVZ.js";
5
5
  import {
6
- requireAuth
7
- } from "./chunk-PCNDP5SX.js";
6
+ requireValidAuth
7
+ } from "./chunk-LXQXJULN.js";
8
+ import "./chunk-UYTVTYNB.js";
8
9
 
9
10
  // src/commands/keys.ts
10
11
  var KEYS_DOC_URL = "https://console.anthropic.com/settings/keys";
11
12
  async function byokRequest(method, body) {
12
- const auth = requireAuth();
13
+ const auth = await requireValidAuth();
13
14
  const res = await fetch(`${auth.apiBase}/api/settings/byok`, {
14
15
  method,
15
16
  headers: {
@@ -32,7 +33,7 @@ async function keysSet(key) {
32
33
  closePrompt();
33
34
  }
34
35
  if (!value) {
35
- console.error(" No key provided. Run `intent keys set` to try again.");
36
+ console.error(" No key provided. Run `intentdocs keys set` to try again.");
36
37
  process.exit(1);
37
38
  }
38
39
  try {
@@ -59,11 +60,11 @@ async function keysStatus() {
59
60
  }
60
61
  if (data?.enabled) {
61
62
  console.log(`
62
- Anthropic API key: ${data.maskedKey ?? "(stored but unreadable \u2014 re-run `intent keys set`)"}`);
63
+ Anthropic API key: ${data.maskedKey ?? "(stored but unreadable \u2014 re-run `intentdocs keys set`)"}`);
63
64
  console.log(" AI features run on your key.\n");
64
65
  } else {
65
66
  console.log("\n No Anthropic API key set.");
66
- console.log(" Add one with `intent keys set` to unlock AI features on any plan.\n");
67
+ console.log(" Add one with `intentdocs keys set` to unlock AI features on any plan.\n");
67
68
  }
68
69
  } catch {
69
70
  console.error(" \u2717 Could not reach intentdocs. Check your connection and try again.");
@@ -0,0 +1,206 @@
1
+ import {
2
+ appendNoteToContext,
3
+ storyContextPath
4
+ } from "./chunk-NFIXRIHM.js";
5
+ import {
6
+ matchesStoryRef
7
+ } from "./chunk-LQTPZL2Y.js";
8
+ import {
9
+ amendDecision,
10
+ apiFetch,
11
+ listDecisions,
12
+ retractDecision
13
+ } from "./chunk-YUW3W43S.js";
14
+ import {
15
+ requireConfig
16
+ } from "./chunk-UF535HZL.js";
17
+ import {
18
+ ask,
19
+ closePrompt,
20
+ confirm,
21
+ isInteractive
22
+ } from "./chunk-WRRUCCVZ.js";
23
+ import "./chunk-LXQXJULN.js";
24
+ import "./chunk-UYTVTYNB.js";
25
+
26
+ // src/commands/log.ts
27
+ async function logDecision(title, opts) {
28
+ const config = requireConfig();
29
+ if (!title) {
30
+ title = await ask(" Decision title: ");
31
+ }
32
+ let description = opts?.description;
33
+ if (!description) {
34
+ description = await ask(" Description (what was decided and why): ");
35
+ }
36
+ if (!title?.trim() || !description?.trim()) {
37
+ console.log(" Title and description required.");
38
+ closePrompt();
39
+ return;
40
+ }
41
+ const res = await apiFetch(config, "/decisions", {
42
+ method: "POST",
43
+ headers: { "Content-Type": "application/json" },
44
+ body: JSON.stringify({
45
+ title: title.trim(),
46
+ description: description.trim(),
47
+ category: opts?.category ?? "technical",
48
+ story_id: opts?.story ?? void 0
49
+ })
50
+ });
51
+ if (res.ok) {
52
+ console.log(` \u2713 Decision logged: ${title}`);
53
+ } else {
54
+ console.error(" Failed to log decision.");
55
+ }
56
+ closePrompt();
57
+ }
58
+ async function findDecision(idPrefix) {
59
+ const config = requireConfig();
60
+ const { decisions } = await listDecisions(config);
61
+ const match = decisions.find((d) => d.id.startsWith(idPrefix));
62
+ if (!match) {
63
+ console.error(` No decision found matching "${idPrefix}"`);
64
+ return null;
65
+ }
66
+ return { config, match };
67
+ }
68
+ async function listLoggedDecisions() {
69
+ const config = requireConfig();
70
+ const { decisions } = await listDecisions(config);
71
+ if (decisions.length === 0) {
72
+ console.log(" No decisions logged yet. Run `intent decide` to log one.");
73
+ return;
74
+ }
75
+ console.log();
76
+ for (const d of decisions) {
77
+ const status = d.retracted_at ? " (retracted)" : "";
78
+ console.log(` ${d.id.slice(0, 8)} [${d.category}] ${d.title}${status}`);
79
+ }
80
+ console.log();
81
+ }
82
+ async function amendDecision2(idPrefix, opts) {
83
+ const found = await findDecision(idPrefix);
84
+ if (!found) {
85
+ closePrompt();
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ const { config, match } = found;
90
+ if (match.retracted_at) {
91
+ console.error(` "${match.title}" has been retracted and can't be amended.`);
92
+ closePrompt();
93
+ process.exitCode = 1;
94
+ return;
95
+ }
96
+ let title = opts?.title;
97
+ let description = opts?.description;
98
+ const category = opts?.category;
99
+ if (!title && !description && !category) {
100
+ if (!isInteractive()) {
101
+ console.error(" Nothing to amend \u2014 pass --title, --description, and/or --category.");
102
+ closePrompt();
103
+ process.exitCode = 1;
104
+ return;
105
+ }
106
+ console.log(` Amending: "${match.title}"`);
107
+ title = await ask(` New title (leave blank to keep current): `);
108
+ description = await ask(` New description (leave blank to keep current): `);
109
+ }
110
+ if (!title?.trim() && !description?.trim() && !category) {
111
+ console.log(" Nothing changed.");
112
+ closePrompt();
113
+ return;
114
+ }
115
+ const updated = await amendDecision(config, match.id, {
116
+ ...title?.trim() ? { title: title.trim() } : {},
117
+ ...description?.trim() ? { description: description.trim() } : {},
118
+ ...category ? { category } : {}
119
+ });
120
+ console.log(` \u2713 Decision amended: "${updated.title}"`);
121
+ closePrompt();
122
+ }
123
+ async function deleteDecision(idPrefix, opts) {
124
+ const found = await findDecision(idPrefix);
125
+ if (!found) {
126
+ closePrompt();
127
+ process.exitCode = 1;
128
+ return;
129
+ }
130
+ const { config, match } = found;
131
+ if (match.retracted_at) {
132
+ console.log(` "${match.title}" is already retracted.`);
133
+ closePrompt();
134
+ return;
135
+ }
136
+ console.log(` Retract: "${match.title}"`);
137
+ console.log(` ${match.description}`);
138
+ if (!opts?.yes) {
139
+ if (!isInteractive()) {
140
+ console.error();
141
+ console.error(` \u2717 Refusing to retract "${match.title}" without confirmation \u2014 no TTY is available to confirm.`);
142
+ console.error(` Re-run with --yes to retract non-interactively, or run interactively to confirm.`);
143
+ closePrompt();
144
+ process.exitCode = 1;
145
+ return;
146
+ }
147
+ const proceed = await confirm(" Retract this decision?");
148
+ if (!proceed) {
149
+ console.log(" Not retracted.");
150
+ closePrompt();
151
+ return;
152
+ }
153
+ }
154
+ await retractDecision(config, match.id, opts?.reason);
155
+ console.log(` \u2713 Decision retracted: "${match.title}"`);
156
+ closePrompt();
157
+ }
158
+ async function logNote(storyId, note) {
159
+ const config = requireConfig();
160
+ if (!note) {
161
+ note = await ask(" Note: ");
162
+ }
163
+ if (!note?.trim()) {
164
+ console.log(" Note required.");
165
+ closePrompt();
166
+ return;
167
+ }
168
+ const listRes = await apiFetch(config, "/stories");
169
+ if (!listRes.ok) {
170
+ console.error(" Failed to fetch stories.");
171
+ closePrompt();
172
+ return;
173
+ }
174
+ const data = await listRes.json();
175
+ const match = data.stories.find((s) => matchesStoryRef(s, storyId));
176
+ if (!match) {
177
+ console.error(` No story found matching "${storyId}"`);
178
+ closePrompt();
179
+ return;
180
+ }
181
+ const res = await apiFetch(config, "/stories", {
182
+ method: "PATCH",
183
+ headers: { "Content-Type": "application/json" },
184
+ body: JSON.stringify({
185
+ stories: [{ id: match.id, notes: note.trim() }]
186
+ })
187
+ });
188
+ if (res.ok) {
189
+ console.log(` \u2713 Note added to: ${match.title.slice(0, 60)}`);
190
+ } else {
191
+ console.error(" Failed to add note.");
192
+ }
193
+ const appended = appendNoteToContext(match.id, note.trim());
194
+ if (appended) {
195
+ const relPath = storyContextPath(match.id).replace(process.cwd() + "/", "");
196
+ console.log(` \u2713 Updated local context: ${relPath}`);
197
+ }
198
+ closePrompt();
199
+ }
200
+ export {
201
+ amendDecision2 as amendDecision,
202
+ deleteDecision,
203
+ listLoggedDecisions,
204
+ logDecision,
205
+ logNote
206
+ };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  requireConfig
3
- } from "./chunk-ICOMMHKG.js";
3
+ } from "./chunk-UF535HZL.js";
4
+ import "./chunk-UYTVTYNB.js";
4
5
 
5
6
  // src/commands/map-extract.ts
6
7
  function mapExtract() {
@@ -1,18 +1,20 @@
1
- import {
2
- closePrompt,
3
- confirm
4
- } from "./chunk-WPVDURTJ.js";
5
1
  import {
6
2
  isPlanGated,
7
3
  printUpgradeMessage
8
- } from "./chunk-ITQUQYWB.js";
4
+ } from "./chunk-UR73WX5I.js";
9
5
  import {
10
- apiUrl
11
- } from "./chunk-6XKB6RTU.js";
6
+ apiUrl,
7
+ syncHeaders
8
+ } from "./chunk-YUW3W43S.js";
12
9
  import {
13
10
  requireConfig
14
- } from "./chunk-ICOMMHKG.js";
15
- import "./chunk-PCNDP5SX.js";
11
+ } from "./chunk-UF535HZL.js";
12
+ import {
13
+ closePrompt,
14
+ confirm
15
+ } from "./chunk-WRRUCCVZ.js";
16
+ import "./chunk-LXQXJULN.js";
17
+ import "./chunk-UYTVTYNB.js";
16
18
 
17
19
  // src/commands/map-import.ts
18
20
  import { readFileSync, existsSync } from "fs";
@@ -309,7 +311,7 @@ async function mapImport(filePath, opts) {
309
311
  const uploadSpinner = ora(" Uploading storymap...").start();
310
312
  const res = await fetch(apiUrl(config, "/map-import"), {
311
313
  method: "POST",
312
- headers: { "Content-Type": "application/json" },
314
+ headers: syncHeaders({ "Content-Type": "application/json" }),
313
315
  body: JSON.stringify(storymap)
314
316
  });
315
317
  if (!res.ok) {
@@ -2,7 +2,7 @@
2
2
  var SCHEMA = {
3
3
  $schema: "https://json-schema.org/draft/2020-12/schema",
4
4
  title: "IntentDocs Story Map",
5
- description: "Schema for storymap.json files produced by `intent map extract` and consumed by `intent map import`.",
5
+ description: "Schema for storymap.json files produced by `intentdocs map extract` and consumed by `intentdocs map import`.",
6
6
  type: "object",
7
7
  required: ["schema_version", "source", "product_summary", "backbone"],
8
8
  additionalProperties: false,
@@ -0,0 +1,37 @@
1
+ import {
2
+ authenticatedFetch,
3
+ bindingLabel,
4
+ getAuth
5
+ } from "./chunk-LXQXJULN.js";
6
+ import "./chunk-UYTVTYNB.js";
7
+
8
+ // src/commands/projects.ts
9
+ async function projects() {
10
+ const res = await authenticatedFetch("/api/cli/projects");
11
+ if (!res.ok) {
12
+ const body = await res.json().catch(() => ({}));
13
+ const said = body.message ?? (typeof body.error === "object" && body.error ? body.error.hint ?? body.error.message : void 0);
14
+ console.error(said ?? "Failed to fetch projects. The server returned an error \u2014 try again or check intentdocs.com for status.");
15
+ process.exit(1);
16
+ }
17
+ const data = await res.json();
18
+ console.log(`
19
+ ${data.workspace}`);
20
+ console.log(` Token ${bindingLabel(getAuth()?.binding)}
21
+ `);
22
+ if (data.projects.length === 0) {
23
+ console.log(" No projects here yet. Create one at intentdocs.com first.\n");
24
+ return;
25
+ }
26
+ for (const p of data.projects) {
27
+ const where = p.workspace ? ` \xB7 ${p.workspace.name ?? "workspace"}` : "";
28
+ console.log(` ${p.id} ${p.name}${where}`);
29
+ if (p.description) console.log(` ${p.description.slice(0, 100)}`);
30
+ }
31
+ console.log(`
32
+ ${data.projects.length} ${data.projects.length === 1 ? "project" : "projects"}. Check one out with: intentdocs init
33
+ `);
34
+ }
35
+ export {
36
+ projects
37
+ };
@@ -4,13 +4,15 @@ import {
4
4
  choose,
5
5
  closePrompt,
6
6
  confirm,
7
+ isInteractive,
7
8
  pausePrompt
8
- } from "./chunk-WPVDURTJ.js";
9
+ } from "./chunk-WRRUCCVZ.js";
9
10
  export {
10
11
  ask,
11
12
  askMultiline,
12
13
  choose,
13
14
  closePrompt,
14
15
  confirm,
16
+ isInteractive,
15
17
  pausePrompt
16
18
  };
@@ -1,18 +1,20 @@
1
- import {
2
- ask,
3
- closePrompt
4
- } from "./chunk-WPVDURTJ.js";
5
1
  import {
6
2
  isPlanGated,
7
3
  printUpgradeMessage
8
- } from "./chunk-ITQUQYWB.js";
4
+ } from "./chunk-UR73WX5I.js";
9
5
  import {
10
- apiUrl
11
- } from "./chunk-6XKB6RTU.js";
6
+ apiUrl,
7
+ syncHeaders
8
+ } from "./chunk-YUW3W43S.js";
12
9
  import {
13
10
  requireConfig
14
- } from "./chunk-ICOMMHKG.js";
15
- import "./chunk-PCNDP5SX.js";
11
+ } from "./chunk-UF535HZL.js";
12
+ import {
13
+ ask,
14
+ closePrompt
15
+ } from "./chunk-WRRUCCVZ.js";
16
+ import "./chunk-LXQXJULN.js";
17
+ import "./chunk-UYTVTYNB.js";
16
18
 
17
19
  // src/commands/research.ts
18
20
  import ora from "ora";
@@ -31,7 +33,7 @@ async function research(query) {
31
33
  try {
32
34
  const res = await fetch(apiUrl(config, "/research"), {
33
35
  method: "POST",
34
- headers: { "Content-Type": "application/json" },
36
+ headers: syncHeaders({ "Content-Type": "application/json" }),
35
37
  body: JSON.stringify({ query })
36
38
  });
37
39
  if (!res.ok) {
@@ -0,0 +1,11 @@
1
+ import {
2
+ scope
3
+ } from "./chunk-5USVG4DW.js";
4
+ import "./chunk-YUW3W43S.js";
5
+ import "./chunk-UF535HZL.js";
6
+ import "./chunk-WRRUCCVZ.js";
7
+ import "./chunk-LXQXJULN.js";
8
+ import "./chunk-UYTVTYNB.js";
9
+ export {
10
+ scope
11
+ };
@@ -0,0 +1,14 @@
1
+ import {
2
+ setup
3
+ } from "./chunk-EEKEF2FD.js";
4
+ import "./chunk-HEHHSSUM.js";
5
+ import "./chunk-NFIXRIHM.js";
6
+ import "./chunk-LQTPZL2Y.js";
7
+ import "./chunk-YUW3W43S.js";
8
+ import "./chunk-UF535HZL.js";
9
+ import "./chunk-WRRUCCVZ.js";
10
+ import "./chunk-LXQXJULN.js";
11
+ import "./chunk-UYTVTYNB.js";
12
+ export {
13
+ setup
14
+ };
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "intentdocs",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "CLI for intentdocs.com — intent-driven development: connect your codebase to your product specs",
5
5
  "bin": {
6
+ "intentdocs": "bin/intentdocs.js",
6
7
  "intent": "bin/intent.js"
7
8
  },
8
9
  "scripts": {
9
- "build": "tsup --clean && chmod +x dist/index.js && chmod +x bin/intent.js",
10
+ "build": "tsup --clean && chmod +x dist/index.js && chmod +x bin/intent.js && chmod +x bin/intentdocs.js",
11
+ "postinstall": "echo '\\n intentdocs installed.\\n Commands: intentdocs (canonical), intent (alias — may collide with other tools)\\n'",
10
12
  "dev": "tsup --watch",
11
13
  "test": "vitest run",
12
14
  "prepublishOnly": "npm run build"
@@ -1,123 +0,0 @@
1
- import {
2
- writeConfig
3
- } from "./chunk-ICOMMHKG.js";
4
- import {
5
- getAuth
6
- } from "./chunk-PCNDP5SX.js";
7
-
8
- // src/lib/api.ts
9
- var AuthError = class extends Error {
10
- constructor(message) {
11
- super(message);
12
- this.name = "AuthError";
13
- }
14
- };
15
- async function refreshSyncToken(config) {
16
- const auth = getAuth();
17
- if (!auth || !config.projectId || !config.mapId) return null;
18
- try {
19
- const res = await fetch(
20
- `${auth.apiBase}/api/cli/projects/${config.projectId}/maps`,
21
- { headers: { Authorization: `Bearer ${auth.token}`, "Content-Type": "application/json" } }
22
- );
23
- if (!res.ok) return null;
24
- const { maps } = await res.json();
25
- const map = maps.find((m) => m.id === config.mapId);
26
- if (!map) return null;
27
- const updated = { ...config, syncToken: map.syncToken };
28
- writeConfig(updated);
29
- return map.syncToken;
30
- } catch {
31
- return null;
32
- }
33
- }
34
- async function apiFetch(config, path, init) {
35
- const res = await fetch(apiUrl(config, path), init);
36
- if (res.status === 401) {
37
- const newToken = await refreshSyncToken(config);
38
- if (newToken) {
39
- const refreshedConfig = { ...config, syncToken: newToken };
40
- const retry = await fetch(apiUrl(refreshedConfig, path), init);
41
- if (retry.ok) return retry;
42
- }
43
- throw new AuthError(
44
- "Session expired. Run `intent login` then `intent init` to re-authenticate."
45
- );
46
- }
47
- if (res.status === 403) {
48
- throw new AuthError(
49
- "Access denied. You may not have permission for this project. Run `intent login`."
50
- );
51
- }
52
- if (!res.ok) throw new Error(`API error: ${res.status}`);
53
- return res;
54
- }
55
- function apiUrl(config, path) {
56
- return `${config.apiBase}/api/sync/${config.syncToken}${path}`;
57
- }
58
- async function listStories(config) {
59
- const res = await apiFetch(config, "/stories");
60
- return res.json();
61
- }
62
- async function getContext(config) {
63
- const res = await apiFetch(config, "/context");
64
- return res.text();
65
- }
66
- async function updateStories(config, stories) {
67
- const res = await apiFetch(config, "/stories", {
68
- method: "PATCH",
69
- headers: { "Content-Type": "application/json" },
70
- body: JSON.stringify({ stories })
71
- });
72
- return res.json();
73
- }
74
- async function uploadScreenshot(config, storyId, screenshot) {
75
- try {
76
- const form = new FormData();
77
- form.append("story_id", storyId);
78
- form.append("image", new Blob([screenshot.buffer], { type: screenshot.mimeType }), screenshot.filename);
79
- const res = await apiFetch(config, "/screenshots", {
80
- method: "POST",
81
- body: form
82
- });
83
- return await res.json();
84
- } catch {
85
- return null;
86
- }
87
- }
88
- async function createStories(config, stories) {
89
- const res = await apiFetch(config, "/stories", {
90
- method: "POST",
91
- headers: { "Content-Type": "application/json" },
92
- body: JSON.stringify({ stories })
93
- });
94
- return res.json();
95
- }
96
- async function reportCriteria(config, storyId, results) {
97
- const res = await apiFetch(config, "/criteria", {
98
- method: "PATCH",
99
- headers: { "Content-Type": "application/json" },
100
- body: JSON.stringify({ story_id: storyId, results })
101
- });
102
- return res.json();
103
- }
104
- async function raiseBlocker(config, payload) {
105
- const res = await apiFetch(config, "/blocker", {
106
- method: "POST",
107
- headers: { "Content-Type": "application/json" },
108
- body: JSON.stringify(payload)
109
- });
110
- return res.json();
111
- }
112
-
113
- export {
114
- apiFetch,
115
- apiUrl,
116
- listStories,
117
- getContext,
118
- updateStories,
119
- uploadScreenshot,
120
- createStories,
121
- reportCriteria,
122
- raiseBlocker
123
- };
@@ -1,34 +0,0 @@
1
- // src/lib/auth.ts
2
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
3
- import { join } from "path";
4
- import { homedir } from "os";
5
- var AUTH_DIR = join(homedir(), ".intent");
6
- var AUTH_FILE = join(AUTH_DIR, "auth.json");
7
- function getAuth() {
8
- try {
9
- const raw = readFileSync(AUTH_FILE, "utf-8");
10
- return JSON.parse(raw);
11
- } catch {
12
- return null;
13
- }
14
- }
15
- function saveAuth(data) {
16
- if (!existsSync(AUTH_DIR)) mkdirSync(AUTH_DIR, { recursive: true });
17
- writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
18
- }
19
- function requireAuth() {
20
- const auth = getAuth();
21
- if (!auth) {
22
- console.error("Not logged in. Run: intent login");
23
- process.exit(1);
24
- }
25
- return auth;
26
- }
27
- var API_BASE = "https://intentdocs.com";
28
-
29
- export {
30
- getAuth,
31
- saveAuth,
32
- requireAuth,
33
- API_BASE
34
- };