@doow/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.
Files changed (43) hide show
  1. package/README.md +75 -0
  2. package/dist/cjs/auth/api-key.js +159 -0
  3. package/dist/cjs/auth/api-key.js.map +1 -0
  4. package/dist/cjs/auth/detect.js +173 -0
  5. package/dist/cjs/auth/detect.js.map +1 -0
  6. package/dist/cjs/auth/device-flow.js +135 -0
  7. package/dist/cjs/auth/device-flow.js.map +1 -0
  8. package/dist/cjs/auth/keyring.js +118 -0
  9. package/dist/cjs/auth/keyring.js.map +1 -0
  10. package/dist/cjs/auth/pkce.js +243 -0
  11. package/dist/cjs/auth/pkce.js.map +1 -0
  12. package/dist/cjs/auth/refresh.js +203 -0
  13. package/dist/cjs/auth/refresh.js.map +1 -0
  14. package/dist/cjs/config/env.js +44 -0
  15. package/dist/cjs/config/env.js.map +1 -0
  16. package/dist/cjs/config/store.js +178 -0
  17. package/dist/cjs/config/store.js.map +1 -0
  18. package/dist/cjs/index.js +48 -0
  19. package/dist/cjs/index.js.map +1 -0
  20. package/dist/cli.cjs +34372 -0
  21. package/dist/cli.cjs.map +1 -0
  22. package/dist/esm/auth/api-key.js +154 -0
  23. package/dist/esm/auth/api-key.js.map +1 -0
  24. package/dist/esm/auth/detect.js +150 -0
  25. package/dist/esm/auth/detect.js.map +1 -0
  26. package/dist/esm/auth/device-flow.js +132 -0
  27. package/dist/esm/auth/device-flow.js.map +1 -0
  28. package/dist/esm/auth/keyring.js +116 -0
  29. package/dist/esm/auth/keyring.js.map +1 -0
  30. package/dist/esm/auth/pkce.js +220 -0
  31. package/dist/esm/auth/pkce.js.map +1 -0
  32. package/dist/esm/auth/refresh.js +198 -0
  33. package/dist/esm/auth/refresh.js.map +1 -0
  34. package/dist/esm/config/env.js +38 -0
  35. package/dist/esm/config/env.js.map +1 -0
  36. package/dist/esm/config/store.js +166 -0
  37. package/dist/esm/config/store.js.map +1 -0
  38. package/dist/esm/index.js +15 -0
  39. package/dist/esm/index.js.map +1 -0
  40. package/dist/mcp.cjs +8 -0
  41. package/dist/mcp.cjs.map +1 -0
  42. package/dist/types/index.d.ts +369 -0
  43. package/package.json +62 -0
@@ -0,0 +1,178 @@
1
+ 'use strict';
2
+
3
+ var promises = require('node:fs/promises');
4
+ var node_path = require('node:path');
5
+ var node_os = require('node:os');
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Constants / defaults
9
+ // ---------------------------------------------------------------------------
10
+ const DEFAULT_PROFILE_NAME = 'default';
11
+ const DEFAULT_CONFIG = {
12
+ activeProfile: DEFAULT_PROFILE_NAME,
13
+ profiles: {
14
+ [DEFAULT_PROFILE_NAME]: { name: DEFAULT_PROFILE_NAME },
15
+ },
16
+ };
17
+ const DEFAULT_CREDENTIALS = {
18
+ profiles: {},
19
+ };
20
+ // ---------------------------------------------------------------------------
21
+ // Config directory
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * Returns the Doow config directory path.
25
+ * Prefers $DOOW_CONFIG_DIR when set; falls back to ~/.doow.
26
+ * Creates the directory (mode 0o700) if it does not yet exist.
27
+ */
28
+ async function getConfigDir() {
29
+ const dir = process.env['DOOW_CONFIG_DIR'] ?? node_path.join(node_os.homedir(), '.doow');
30
+ await promises.mkdir(dir, { recursive: true, mode: 0o700 });
31
+ await promises.chmod(dir, 0o700);
32
+ return dir;
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Atomic write helper
36
+ // ---------------------------------------------------------------------------
37
+ async function atomicWrite(filePath, data) {
38
+ const tmp = `${filePath}.tmp`;
39
+ try {
40
+ await promises.writeFile(tmp, data, { encoding: 'utf-8', mode: 0o600 });
41
+ await promises.rename(tmp, filePath);
42
+ }
43
+ catch (err) {
44
+ // Clean up temp file on failure, best-effort
45
+ await promises.rm(tmp, { force: true }).catch(() => undefined);
46
+ throw err;
47
+ }
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // config.json
51
+ // ---------------------------------------------------------------------------
52
+ /** Reads ~/.doow/config.json. Returns the default config if the file is absent. */
53
+ async function readConfig() {
54
+ const dir = await getConfigDir();
55
+ const filePath = node_path.join(dir, 'config.json');
56
+ try {
57
+ const raw = await promises.readFile(filePath, 'utf-8');
58
+ return JSON.parse(raw);
59
+ }
60
+ catch (err) {
61
+ if (isEnoent(err))
62
+ return structuredClone(DEFAULT_CONFIG);
63
+ throw err;
64
+ }
65
+ }
66
+ /** Writes ~/.doow/config.json atomically with 0o600 perms. */
67
+ async function writeConfig(config) {
68
+ const dir = await getConfigDir();
69
+ const filePath = node_path.join(dir, 'config.json');
70
+ await atomicWrite(filePath, JSON.stringify(config, null, 2));
71
+ }
72
+ // ---------------------------------------------------------------------------
73
+ // credentials.json
74
+ // ---------------------------------------------------------------------------
75
+ /** Reads ~/.doow/credentials.json. Returns empty credentials if absent. */
76
+ async function readCredentials() {
77
+ const dir = await getConfigDir();
78
+ const filePath = node_path.join(dir, 'credentials.json');
79
+ try {
80
+ const raw = await promises.readFile(filePath, 'utf-8');
81
+ return JSON.parse(raw);
82
+ }
83
+ catch (err) {
84
+ if (isEnoent(err))
85
+ return structuredClone(DEFAULT_CREDENTIALS);
86
+ throw err;
87
+ }
88
+ }
89
+ /** Writes ~/.doow/credentials.json atomically with 0o600 perms. */
90
+ async function writeCredentials(creds) {
91
+ const dir = await getConfigDir();
92
+ const filePath = node_path.join(dir, 'credentials.json');
93
+ await atomicWrite(filePath, JSON.stringify(creds, null, 2));
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // Active profile
97
+ // ---------------------------------------------------------------------------
98
+ /** Returns the currently active Profile object. */
99
+ async function getActiveProfile() {
100
+ const config = await readConfig();
101
+ const profile = config.profiles[config.activeProfile];
102
+ if (!profile) {
103
+ // Graceful degradation: return synthetic default
104
+ return { name: config.activeProfile };
105
+ }
106
+ return profile;
107
+ }
108
+ /** Sets the active profile name and persists config. Throws if the profile doesn't exist. */
109
+ async function setActiveProfile(name) {
110
+ const config = await readConfig();
111
+ if (!config.profiles[name]) {
112
+ throw new Error(`Profile "${name}" does not exist.`);
113
+ }
114
+ config.activeProfile = name;
115
+ await writeConfig(config);
116
+ }
117
+ // ---------------------------------------------------------------------------
118
+ // Profile credentials
119
+ // ---------------------------------------------------------------------------
120
+ /**
121
+ * Returns credentials for the given profile name.
122
+ * Defaults to the currently active profile if name is omitted.
123
+ */
124
+ async function getProfileCredentials(profileName) {
125
+ const name = profileName ?? (await readConfig()).activeProfile;
126
+ const creds = await readCredentials();
127
+ return creds.profiles[name];
128
+ }
129
+ /** Stores credentials for the given profile, merging with existing. */
130
+ async function setProfileCredentials(profileName, creds) {
131
+ const existing = await readCredentials();
132
+ existing.profiles[profileName] = creds;
133
+ await writeCredentials(existing);
134
+ }
135
+ /** Removes all credentials for the given profile. */
136
+ async function clearProfileCredentials(profileName) {
137
+ const creds = await readCredentials();
138
+ delete creds.profiles[profileName];
139
+ await writeCredentials(creds);
140
+ }
141
+ // ---------------------------------------------------------------------------
142
+ // Profile lifecycle
143
+ // ---------------------------------------------------------------------------
144
+ /**
145
+ * Deletes a profile from config + credentials.
146
+ * Throws if the profile is currently active — caller must switch first.
147
+ */
148
+ async function deleteProfile(name) {
149
+ const config = await readConfig();
150
+ if (config.activeProfile === name) {
151
+ throw new Error(`Cannot delete the active profile "${name}". Switch to another profile first.`);
152
+ }
153
+ delete config.profiles[name];
154
+ await writeConfig(config);
155
+ await clearProfileCredentials(name);
156
+ }
157
+ // ---------------------------------------------------------------------------
158
+ // Utility
159
+ // ---------------------------------------------------------------------------
160
+ function isEnoent(err) {
161
+ return (typeof err === 'object' &&
162
+ err !== null &&
163
+ 'code' in err &&
164
+ err.code === 'ENOENT');
165
+ }
166
+
167
+ exports.clearProfileCredentials = clearProfileCredentials;
168
+ exports.deleteProfile = deleteProfile;
169
+ exports.getActiveProfile = getActiveProfile;
170
+ exports.getConfigDir = getConfigDir;
171
+ exports.getProfileCredentials = getProfileCredentials;
172
+ exports.readConfig = readConfig;
173
+ exports.readCredentials = readCredentials;
174
+ exports.setActiveProfile = setActiveProfile;
175
+ exports.setProfileCredentials = setProfileCredentials;
176
+ exports.writeConfig = writeConfig;
177
+ exports.writeCredentials = writeCredentials;
178
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sources":["../../../../src/config/store.ts"],"sourcesContent":[null],"names":["join","homedir","mkdir","chmod","writeFile","rename","rm","readFile"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ var store = require('./config/store.js');
4
+ var env = require('./config/env.js');
5
+ var keyring = require('./auth/keyring.js');
6
+ var pkce = require('./auth/pkce.js');
7
+ var deviceFlow = require('./auth/device-flow.js');
8
+ var apiKey = require('./auth/api-key.js');
9
+ var refresh = require('./auth/refresh.js');
10
+ var detect = require('./auth/detect.js');
11
+
12
+ // @doow/cli library entry point
13
+ // Re-exports for programmatic usage
14
+ const VERSION = '0.1.0';
15
+
16
+ exports.clearProfileCredentials = store.clearProfileCredentials;
17
+ exports.deleteProfile = store.deleteProfile;
18
+ exports.getActiveProfile = store.getActiveProfile;
19
+ exports.getConfigDir = store.getConfigDir;
20
+ exports.getProfileCredentials = store.getProfileCredentials;
21
+ exports.readConfig = store.readConfig;
22
+ exports.readCredentials = store.readCredentials;
23
+ exports.setActiveProfile = store.setActiveProfile;
24
+ exports.setProfileCredentials = store.setProfileCredentials;
25
+ exports.writeConfig = store.writeConfig;
26
+ exports.writeCredentials = store.writeCredentials;
27
+ exports.getApiUrl = env.getApiUrl;
28
+ exports.isAgentMode = env.isAgentMode;
29
+ exports.isCI = env.isCI;
30
+ exports.isTTY = env.isTTY;
31
+ exports.shouldShowUI = env.shouldShowUI;
32
+ exports.createCredentialStore = keyring.createCredentialStore;
33
+ exports.executePkceFlow = pkce.executePkceFlow;
34
+ exports.generatePkcePair = pkce.generatePkcePair;
35
+ exports.executeDeviceFlow = deviceFlow.executeDeviceFlow;
36
+ exports.authenticateWithApiKey = apiKey.authenticateWithApiKey;
37
+ exports.readTokenFromStdin = apiKey.readTokenFromStdin;
38
+ exports.resolveAuth = apiKey.resolveAuth;
39
+ exports.validateApiKey = apiKey.validateApiKey;
40
+ exports.acquireLock = refresh.acquireLock;
41
+ exports.needsRefresh = refresh.needsRefresh;
42
+ exports.refreshToken = refresh.refreshToken;
43
+ exports.releaseLock = refresh.releaseLock;
44
+ exports.canBindLocalhost = detect.canBindLocalhost;
45
+ exports.detectAuthMethod = detect.detectAuthMethod;
46
+ exports.executeAutoLogin = detect.executeAutoLogin;
47
+ exports.VERSION = VERSION;
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;AAAA;AACA;AAEO,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}