@codata-io/cli 0.2.2
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/bin/codata.d.ts +3 -0
- package/dist/bin/codata.d.ts.map +1 -0
- package/dist/bin/codata.js +3 -0
- package/dist/bin/codata.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +192 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/api.d.ts +6 -0
- package/dist/src/commands/api.d.ts.map +1 -0
- package/dist/src/commands/api.js +79 -0
- package/dist/src/commands/api.js.map +1 -0
- package/dist/src/commands/branches.d.ts +14 -0
- package/dist/src/commands/branches.d.ts.map +1 -0
- package/dist/src/commands/branches.js +86 -0
- package/dist/src/commands/branches.js.map +1 -0
- package/dist/src/commands/export.d.ts +4 -0
- package/dist/src/commands/export.d.ts.map +1 -0
- package/dist/src/commands/export.js +20 -0
- package/dist/src/commands/export.js.map +1 -0
- package/dist/src/commands/init.d.ts +5 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +175 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/keys.d.ts +37 -0
- package/dist/src/commands/keys.d.ts.map +1 -0
- package/dist/src/commands/keys.js +142 -0
- package/dist/src/commands/keys.js.map +1 -0
- package/dist/src/commands/login.d.ts +6 -0
- package/dist/src/commands/login.d.ts.map +1 -0
- package/dist/src/commands/login.js +14 -0
- package/dist/src/commands/login.js.map +1 -0
- package/dist/src/commands/scaffold.d.ts +5 -0
- package/dist/src/commands/scaffold.d.ts.map +1 -0
- package/dist/src/commands/scaffold.js +202 -0
- package/dist/src/commands/scaffold.js.map +1 -0
- package/dist/src/commands/workspaces.d.ts +10 -0
- package/dist/src/commands/workspaces.d.ts.map +1 -0
- package/dist/src/commands/workspaces.js +80 -0
- package/dist/src/commands/workspaces.js.map +1 -0
- package/dist/src/config.d.ts +38 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +159 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/oauth.d.ts +15 -0
- package/dist/src/oauth.d.ts.map +1 -0
- package/dist/src/oauth.js +272 -0
- package/dist/src/oauth.js.map +1 -0
- package/dist/src/output.d.ts +10 -0
- package/dist/src/output.d.ts.map +1 -0
- package/dist/src/output.js +69 -0
- package/dist/src/output.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Codata CLI — Init (MCP Setup) Command
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import os from 'os';
|
|
7
|
+
import { getMcpUrl } from '../config.js';
|
|
8
|
+
import { success, error as printError, info } from '../output.js';
|
|
9
|
+
export async function initCommand(options) {
|
|
10
|
+
const mcpUrl = getMcpUrl();
|
|
11
|
+
const isGlobal = options.global ?? false;
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log(' 🚀 Codata MCP Setup');
|
|
14
|
+
console.log(` Server: ${mcpUrl}`);
|
|
15
|
+
console.log(` Mode: ${isGlobal ? 'global (user settings)' : 'workspace (.vscode/mcp.json)'}`);
|
|
16
|
+
console.log('');
|
|
17
|
+
const editors = detectEditors();
|
|
18
|
+
const available = editors.filter(e => e.detected);
|
|
19
|
+
if (available.length === 0) {
|
|
20
|
+
printError('No supported editors detected.');
|
|
21
|
+
info('Supported: VS Code, Cursor, Claude Code, Claude Desktop');
|
|
22
|
+
info(`Manual: Create .vscode/mcp.json with: { "servers": { "codata": { "type": "http", "url": "${mcpUrl}" } } }`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (options.editor) {
|
|
26
|
+
const needle = options.editor.toLowerCase().replace(/[-_ ]/g, '');
|
|
27
|
+
const editor = editors.find(e => e.name.toLowerCase().replace(/[-_ ]/g, '').includes(needle));
|
|
28
|
+
if (!editor) {
|
|
29
|
+
printError(`Editor "${options.editor}" not found.`);
|
|
30
|
+
info('Available: ' + editors.map(e => e.name).join(', '));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const writtenPath = editor.write(mcpUrl, isGlobal);
|
|
34
|
+
success(`${editor.name} configured → ${writtenPath}`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
for (const editor of available) {
|
|
38
|
+
try {
|
|
39
|
+
const writtenPath = editor.write(mcpUrl, isGlobal);
|
|
40
|
+
success(`${editor.name} → ${writtenPath}`);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
printError(`${editor.name}: ${err.message}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
console.log('');
|
|
47
|
+
info('Done! Open your editor and start a Copilot/AI chat.');
|
|
48
|
+
}
|
|
49
|
+
function detectEditors() {
|
|
50
|
+
const home = os.homedir();
|
|
51
|
+
const platform = process.platform;
|
|
52
|
+
const vscodeDir = platform === 'darwin'
|
|
53
|
+
? path.join(home, 'Library', 'Application Support', 'Code', 'User')
|
|
54
|
+
: platform === 'win32'
|
|
55
|
+
? path.join(process.env.APPDATA || '', 'Code', 'User')
|
|
56
|
+
: path.join(home, '.config', 'Code', 'User');
|
|
57
|
+
const cursorDir = platform === 'darwin'
|
|
58
|
+
? path.join(home, 'Library', 'Application Support', 'Cursor', 'User')
|
|
59
|
+
: platform === 'win32'
|
|
60
|
+
? path.join(process.env.APPDATA || '', 'Cursor', 'User')
|
|
61
|
+
: path.join(home, '.config', 'Cursor', 'User');
|
|
62
|
+
const claudeDir = platform === 'darwin'
|
|
63
|
+
? path.join(home, 'Library', 'Application Support', 'Claude')
|
|
64
|
+
: platform === 'win32'
|
|
65
|
+
? path.join(process.env.APPDATA || '', 'Claude')
|
|
66
|
+
: path.join(home, '.config', 'Claude');
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
name: 'VS Code',
|
|
70
|
+
detected: fs.existsSync(vscodeDir),
|
|
71
|
+
write: (url, global) => global
|
|
72
|
+
? writeSettingsJson(vscodeDir, url)
|
|
73
|
+
: writeWorkspaceMcpJson(url),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'Cursor',
|
|
77
|
+
detected: fs.existsSync(cursorDir),
|
|
78
|
+
write: (url, global) => global
|
|
79
|
+
? writeCursorMcpJson(cursorDir, url)
|
|
80
|
+
: writeWorkspaceMcpJson(url),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'Claude Code',
|
|
84
|
+
detected: isClaudeCodeInstalled(),
|
|
85
|
+
write: (url, global) => global
|
|
86
|
+
? writeClaudeCodeGlobalConfig(url)
|
|
87
|
+
: writeClaudeCodeProjectConfig(url),
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'Claude Desktop',
|
|
91
|
+
detected: fs.existsSync(claudeDir),
|
|
92
|
+
write: (url, _global) => writeClaudeDesktopConfig(claudeDir, url),
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
function writeWorkspaceMcpJson(mcpUrl) {
|
|
97
|
+
const dir = path.join(process.cwd(), '.vscode');
|
|
98
|
+
if (!fs.existsSync(dir))
|
|
99
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
100
|
+
const filePath = path.join(dir, 'mcp.json');
|
|
101
|
+
const config = safeReadJson(filePath);
|
|
102
|
+
if (!config.servers)
|
|
103
|
+
config.servers = {};
|
|
104
|
+
config.servers.codata = { type: 'http', url: mcpUrl };
|
|
105
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n');
|
|
106
|
+
return filePath;
|
|
107
|
+
}
|
|
108
|
+
function writeSettingsJson(configDir, mcpUrl) {
|
|
109
|
+
const filePath = path.join(configDir, 'settings.json');
|
|
110
|
+
const settings = safeReadJson(filePath);
|
|
111
|
+
if (!settings.mcp)
|
|
112
|
+
settings.mcp = {};
|
|
113
|
+
if (!settings.mcp.servers)
|
|
114
|
+
settings.mcp.servers = {};
|
|
115
|
+
settings.mcp.servers.codata = { type: 'http', url: mcpUrl };
|
|
116
|
+
fs.writeFileSync(filePath, JSON.stringify(settings, null, 2) + '\n');
|
|
117
|
+
return filePath;
|
|
118
|
+
}
|
|
119
|
+
function writeCursorMcpJson(configDir, mcpUrl) {
|
|
120
|
+
const filePath = path.join(configDir, 'mcp.json');
|
|
121
|
+
const config = safeReadJson(filePath);
|
|
122
|
+
if (!config.mcpServers)
|
|
123
|
+
config.mcpServers = {};
|
|
124
|
+
config.mcpServers.codata = { type: 'http', url: mcpUrl };
|
|
125
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n');
|
|
126
|
+
return filePath;
|
|
127
|
+
}
|
|
128
|
+
function writeClaudeDesktopConfig(configDir, mcpUrl) {
|
|
129
|
+
if (!fs.existsSync(configDir))
|
|
130
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
131
|
+
const filePath = path.join(configDir, 'claude_desktop_config.json');
|
|
132
|
+
const config = safeReadJson(filePath);
|
|
133
|
+
if (!config.mcpServers)
|
|
134
|
+
config.mcpServers = {};
|
|
135
|
+
config.mcpServers.codata = { type: 'http', url: mcpUrl };
|
|
136
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n');
|
|
137
|
+
return filePath;
|
|
138
|
+
}
|
|
139
|
+
function isClaudeCodeInstalled() {
|
|
140
|
+
// Claude Code stores its global config at ~/.claude.json
|
|
141
|
+
const globalConfig = path.join(os.homedir(), '.claude.json');
|
|
142
|
+
if (fs.existsSync(globalConfig))
|
|
143
|
+
return true;
|
|
144
|
+
// Also check if the claude CLI is available via the .claude directory
|
|
145
|
+
const claudeCodeDir = path.join(os.homedir(), '.claude');
|
|
146
|
+
return fs.existsSync(claudeCodeDir);
|
|
147
|
+
}
|
|
148
|
+
function writeClaudeCodeProjectConfig(mcpUrl) {
|
|
149
|
+
const filePath = path.join(process.cwd(), '.mcp.json');
|
|
150
|
+
const config = safeReadJson(filePath);
|
|
151
|
+
if (!config.mcpServers)
|
|
152
|
+
config.mcpServers = {};
|
|
153
|
+
config.mcpServers.codata = { url: mcpUrl };
|
|
154
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n');
|
|
155
|
+
return filePath;
|
|
156
|
+
}
|
|
157
|
+
function writeClaudeCodeGlobalConfig(mcpUrl) {
|
|
158
|
+
const filePath = path.join(os.homedir(), '.claude.json');
|
|
159
|
+
const config = safeReadJson(filePath);
|
|
160
|
+
if (!config.mcpServers)
|
|
161
|
+
config.mcpServers = {};
|
|
162
|
+
config.mcpServers.codata = { url: mcpUrl };
|
|
163
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n');
|
|
164
|
+
return filePath;
|
|
165
|
+
}
|
|
166
|
+
function safeReadJson(filePath) {
|
|
167
|
+
try {
|
|
168
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
169
|
+
return JSON.parse(content.replace(/^\uFEFF/, '').replace(/,\s*([\]}])/g, '$1'));
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return {};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a new API key for a workspace and optionally store it locally.
|
|
3
|
+
*/
|
|
4
|
+
export declare function keysCreateCommand(nameOrId: string, options: {
|
|
5
|
+
name?: string;
|
|
6
|
+
permissions?: string;
|
|
7
|
+
store?: boolean;
|
|
8
|
+
json?: boolean;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* List all API keys for a workspace.
|
|
12
|
+
*/
|
|
13
|
+
export declare function keysListCommand(nameOrId: string, options: {
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Revoke an API key.
|
|
18
|
+
*/
|
|
19
|
+
export declare function keysRevokeCommand(nameOrId: string, keyId: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Rotate an API key (revoke old, issue new).
|
|
22
|
+
*/
|
|
23
|
+
export declare function keysRotateCommand(nameOrId: string, keyId: string, options: {
|
|
24
|
+
store?: boolean;
|
|
25
|
+
json?: boolean;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Show the currently stored (active) key for a workspace.
|
|
29
|
+
*/
|
|
30
|
+
export declare function keysCurrentCommand(nameOrId: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* List all locally stored keys.
|
|
33
|
+
*/
|
|
34
|
+
export declare function keysStoredCommand(options: {
|
|
35
|
+
json?: boolean;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/commands/keys.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAChF,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3C,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBxE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBlF"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Codata CLI — API Key Management Commands
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
import { createCliClient, storeKey, getStoredKey, removeStoredKey, getStoredKeys } from '../config.js';
|
|
5
|
+
import { printTable, heading, success, info, warn, printJson, } from '../output.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create a new API key for a workspace and optionally store it locally.
|
|
8
|
+
*/
|
|
9
|
+
export async function keysCreateCommand(nameOrId, options) {
|
|
10
|
+
const client = createCliClient();
|
|
11
|
+
const ws = await client.findWorkspace(nameOrId);
|
|
12
|
+
const keyName = options.name || `cli-${Date.now()}`;
|
|
13
|
+
const permissions = (options.permissions ?? 'full');
|
|
14
|
+
const result = await client.keys.create(ws.id, keyName, permissions);
|
|
15
|
+
if (options.json) {
|
|
16
|
+
printJson({ ...result.key, plainTextKey: result.plainTextKey });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
heading('API Key Created');
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log(` Name: ${result.key.name}`);
|
|
22
|
+
console.log(` Key ID: ${result.key.id}`);
|
|
23
|
+
console.log(` Permissions: ${result.key.permissions}`);
|
|
24
|
+
console.log(` Prefix: ${result.key.keyPrefix}`);
|
|
25
|
+
console.log('');
|
|
26
|
+
console.log(` 🔑 Key: ${result.plainTextKey}`);
|
|
27
|
+
console.log('');
|
|
28
|
+
warn('Save this key now — it will not be shown again!');
|
|
29
|
+
// Optionally store locally
|
|
30
|
+
if (options.store !== false) {
|
|
31
|
+
storeKey(ws.id, result.plainTextKey, keyName);
|
|
32
|
+
info(`Key stored locally for workspace "${ws.name}".`);
|
|
33
|
+
info('It will be used automatically for API calls to this workspace.');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* List all API keys for a workspace.
|
|
38
|
+
*/
|
|
39
|
+
export async function keysListCommand(nameOrId, options) {
|
|
40
|
+
const client = createCliClient();
|
|
41
|
+
const ws = await client.findWorkspace(nameOrId);
|
|
42
|
+
const keys = await client.keys.list(ws.id);
|
|
43
|
+
if (keys.length === 0) {
|
|
44
|
+
info(`No API keys for workspace "${ws.name}". Create one: codata keys create ${nameOrId}`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (options.json) {
|
|
48
|
+
printJson(keys);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const storedKey = getStoredKey(ws.id);
|
|
52
|
+
printTable(['Name', 'Key ID', 'Prefix', 'Permissions', 'Last Used', 'Active'], keys.map(k => [
|
|
53
|
+
k.name,
|
|
54
|
+
k.id,
|
|
55
|
+
k.keyPrefix,
|
|
56
|
+
k.permissions,
|
|
57
|
+
k.lastUsedAt ? new Date(k.lastUsedAt).toLocaleDateString() : 'Never',
|
|
58
|
+
storedKey?.startsWith(k.keyPrefix) ? '✓ (stored)' : '',
|
|
59
|
+
]));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Revoke an API key.
|
|
63
|
+
*/
|
|
64
|
+
export async function keysRevokeCommand(nameOrId, keyId) {
|
|
65
|
+
const client = createCliClient();
|
|
66
|
+
const ws = await client.findWorkspace(nameOrId);
|
|
67
|
+
await client.keys.revoke(ws.id, keyId);
|
|
68
|
+
success(`API key ${keyId} revoked.`);
|
|
69
|
+
// Clean up local storage if this was the stored key
|
|
70
|
+
const storedKey = getStoredKey(ws.id);
|
|
71
|
+
if (storedKey) {
|
|
72
|
+
removeStoredKey(ws.id);
|
|
73
|
+
info('Removed locally stored key for this workspace.');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Rotate an API key (revoke old, issue new).
|
|
78
|
+
*/
|
|
79
|
+
export async function keysRotateCommand(nameOrId, keyId, options) {
|
|
80
|
+
const client = createCliClient();
|
|
81
|
+
const ws = await client.findWorkspace(nameOrId);
|
|
82
|
+
const result = await client.keys.rotate(ws.id, keyId);
|
|
83
|
+
if (options.json) {
|
|
84
|
+
printJson({ ...result.key, plainTextKey: result.plainTextKey });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
heading('API Key Rotated');
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log(` Name: ${result.key.name}`);
|
|
90
|
+
console.log(` New ID: ${result.key.id}`);
|
|
91
|
+
console.log('');
|
|
92
|
+
console.log(` 🔑 New Key: ${result.plainTextKey}`);
|
|
93
|
+
console.log('');
|
|
94
|
+
warn('Save this key now — it will not be shown again!');
|
|
95
|
+
if (options.store !== false) {
|
|
96
|
+
storeKey(ws.id, result.plainTextKey, result.key.name);
|
|
97
|
+
info('Updated locally stored key.');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Show the currently stored (active) key for a workspace.
|
|
102
|
+
*/
|
|
103
|
+
export async function keysCurrentCommand(nameOrId) {
|
|
104
|
+
const client = createCliClient();
|
|
105
|
+
const ws = await client.findWorkspace(nameOrId);
|
|
106
|
+
const key = getStoredKey(ws.id);
|
|
107
|
+
if (!key) {
|
|
108
|
+
info(`No locally stored key for workspace "${ws.name}".`);
|
|
109
|
+
info(`Create one: codata keys create ${nameOrId}`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Mask the key (show first 12 chars + last 4)
|
|
113
|
+
const masked = key.length > 16
|
|
114
|
+
? `${key.slice(0, 12)}...${key.slice(-4)}`
|
|
115
|
+
: key.slice(0, 8) + '...';
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log(` Workspace: ${ws.name}`);
|
|
118
|
+
console.log(` Key: ${masked}`);
|
|
119
|
+
console.log('');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* List all locally stored keys.
|
|
123
|
+
*/
|
|
124
|
+
export async function keysStoredCommand(options) {
|
|
125
|
+
const stored = getStoredKeys();
|
|
126
|
+
const entries = Object.entries(stored);
|
|
127
|
+
if (entries.length === 0) {
|
|
128
|
+
info('No locally stored API keys.');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (options.json) {
|
|
132
|
+
printJson(stored);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
printTable(['Workspace ID', 'Name', 'Key Prefix', 'Stored At'], entries.map(([wsId, data]) => [
|
|
136
|
+
wsId,
|
|
137
|
+
data.name,
|
|
138
|
+
data.key.slice(0, 12) + '...',
|
|
139
|
+
new Date(data.storedAt).toLocaleDateString(),
|
|
140
|
+
]));
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/commands/keys.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2CAA2C;AAC3C,+EAA+E;AAE/E,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EACL,UAAU,EACV,OAAO,EACP,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,SAAS,GAEV,MAAM,cAAc,CAAC;AAGtB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAgB,EAChB,OAAiF;IAEjF,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACpD,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,MAAM,CAAqB,CAAC;IAExE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAErE,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAExD,2BAA2B;IAC3B,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QAC5B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,qCAAqC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,gEAAgE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,OAA2B;IAE3B,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAE3C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,8BAA8B,EAAE,CAAC,IAAI,qCAAqC,QAAQ,EAAE,CAAC,CAAC;QAC3F,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAEtC,UAAU,CACR,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,CAAC,EAClE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACZ,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,OAAO;QACpE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;KACvD,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAgB,EAChB,KAAa;IAEb,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC;IAErC,oDAAoD;IACpD,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtC,IAAI,SAAS,EAAE,CAAC;QACd,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,gDAAgD,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAgB,EAChB,KAAa,EACb,OAA4C;IAE5C,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAEtD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAExD,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QAC5B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,IAAI,CAAC,wCAAwC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,8CAA8C;IAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,EAAE;QAC5B,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;QAC1C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;IAE5B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAA2B;IACjE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,6BAA6B,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,CAAC,CAAC;QAClB,OAAO;IACT,CAAC;IAED,UAAU,CACR,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,EACnD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI;QACJ,IAAI,CAAC,IAAI;QACT,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;QAC7B,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,kBAAkB,EAAE;KAC7C,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Codata CLI — Login / Logout / Whoami Commands
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
import { login, logout, whoami } from '../oauth.js';
|
|
5
|
+
export async function loginCommand(options) {
|
|
6
|
+
await login(options);
|
|
7
|
+
}
|
|
8
|
+
export async function logoutCommand() {
|
|
9
|
+
await logout();
|
|
10
|
+
}
|
|
11
|
+
export async function whoamiCommand() {
|
|
12
|
+
await whoami();
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gDAAgD;AAChD,+EAA+E;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA2B;IAC5D,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,EAAE,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/commands/scaffold.ts"],"names":[],"mappings":"AAWA,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Codata CLI — Scaffold Command (Generate Typed API Client)
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { createCliClient, getConfig } from '../config.js';
|
|
6
|
+
import { success, error as printError } from '../output.js';
|
|
7
|
+
export async function scaffoldCommand(nameOrId, options) {
|
|
8
|
+
const client = createCliClient();
|
|
9
|
+
const ws = await client.findWorkspace(nameOrId);
|
|
10
|
+
const spec = (ws.spec?.endpoints?.length ? ws.spec : ws.desiredSpec) ?? ws.spec;
|
|
11
|
+
if (!spec?.endpoints?.length) {
|
|
12
|
+
printError(`Workspace "${ws.name}" has no endpoints. Define endpoints first.`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
const language = (options.lang || getConfig().defaultLanguage || 'typescript');
|
|
16
|
+
const code = generateClient(ws.name, spec, language);
|
|
17
|
+
if (options.output) {
|
|
18
|
+
fs.writeFileSync(options.output, code);
|
|
19
|
+
success(`Written to ${options.output}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log(code);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function generateClient(name, spec, lang) {
|
|
26
|
+
switch (lang) {
|
|
27
|
+
case 'typescript': return generateTypeScript(name, spec);
|
|
28
|
+
case 'javascript': return generateJavaScript(name, spec);
|
|
29
|
+
case 'python': return generatePython(name, spec);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// ── TypeScript ────────────────────────────────────────────────────────────
|
|
33
|
+
function generateTypeScript(name, spec) {
|
|
34
|
+
const lines = [];
|
|
35
|
+
lines.push(`/**`);
|
|
36
|
+
lines.push(` * Auto-generated API client for "${name}"`);
|
|
37
|
+
lines.push(` * Generated by Codata CLI`);
|
|
38
|
+
lines.push(` */\n`);
|
|
39
|
+
for (const asset of spec.assets ?? []) {
|
|
40
|
+
lines.push(`export interface ${pascal(asset.name)} {`);
|
|
41
|
+
for (const f of asset.fields ?? []) {
|
|
42
|
+
const tsType = mapTS(f.type, f.fieldKind);
|
|
43
|
+
const opt = f.required ? '' : '?';
|
|
44
|
+
if (f.description)
|
|
45
|
+
lines.push(` /** ${f.description} */`);
|
|
46
|
+
lines.push(` ${f.name}${opt}: ${tsType};`);
|
|
47
|
+
}
|
|
48
|
+
lines.push(`}\n`);
|
|
49
|
+
}
|
|
50
|
+
lines.push(`export class ${pascal(name)}Client {`);
|
|
51
|
+
lines.push(` constructor(private baseUrl: string, private headers: Record<string, string> = {}) {}\n`);
|
|
52
|
+
lines.push(` private async request<T>(method: string, path: string, body?: any): Promise<T> {`);
|
|
53
|
+
lines.push(` const res = await fetch(\`\${this.baseUrl}\${path}\`, {`);
|
|
54
|
+
lines.push(` method,`);
|
|
55
|
+
lines.push(` headers: { 'Content-Type': 'application/json', ...this.headers },`);
|
|
56
|
+
lines.push(` body: body ? JSON.stringify(body) : undefined,`);
|
|
57
|
+
lines.push(` });`);
|
|
58
|
+
lines.push(` if (!res.ok) throw new Error(\`\${method} \${path}: \${res.status}\`);`);
|
|
59
|
+
lines.push(` return res.json();`);
|
|
60
|
+
lines.push(` }\n`);
|
|
61
|
+
for (const ep of spec.endpoints ?? []) {
|
|
62
|
+
const mName = ep.operationId || methodName(ep);
|
|
63
|
+
const ret = guessReturn(ep, spec.assets ?? []);
|
|
64
|
+
lines.push(` /** ${ep.summary || `${ep.method} ${ep.path}`} */`);
|
|
65
|
+
lines.push(` async ${mName}(${paramsTS(ep)}): Promise<${ret}> {`);
|
|
66
|
+
const pathExpr = ep.path.replace(/:(\w+)/g, '${$1}');
|
|
67
|
+
const hasBody = ep.method !== 'GET' && ep.method !== 'DELETE';
|
|
68
|
+
lines.push(` return this.request('${ep.method}', \`${pathExpr}\`${hasBody ? ', body' : ''});`);
|
|
69
|
+
lines.push(` }\n`);
|
|
70
|
+
}
|
|
71
|
+
lines.push(`}`);
|
|
72
|
+
return lines.join('\n');
|
|
73
|
+
}
|
|
74
|
+
// ── JavaScript ────────────────────────────────────────────────────────────
|
|
75
|
+
function generateJavaScript(name, spec) {
|
|
76
|
+
const lines = [];
|
|
77
|
+
lines.push(`/** Auto-generated API client for "${name}" */\n`);
|
|
78
|
+
lines.push(`export class ${pascal(name)}Client {`);
|
|
79
|
+
lines.push(` constructor(baseUrl, headers = {}) { this.baseUrl = baseUrl; this.headers = headers; }\n`);
|
|
80
|
+
lines.push(` async #request(method, path, body) {`);
|
|
81
|
+
lines.push(` const res = await fetch(\`\${this.baseUrl}\${path}\`, { method, headers: { 'Content-Type': 'application/json', ...this.headers }, body: body ? JSON.stringify(body) : undefined });`);
|
|
82
|
+
lines.push(` if (!res.ok) throw new Error(\`\${method} \${path}: \${res.status}\`);`);
|
|
83
|
+
lines.push(` return res.json();`);
|
|
84
|
+
lines.push(` }\n`);
|
|
85
|
+
for (const ep of spec.endpoints ?? []) {
|
|
86
|
+
const mName = ep.operationId || methodName(ep);
|
|
87
|
+
const pathExpr = ep.path.replace(/:(\w+)/g, '${$1}');
|
|
88
|
+
const hasBody = ep.method !== 'GET' && ep.method !== 'DELETE';
|
|
89
|
+
lines.push(` async ${mName}(${paramsJS(ep)}) { return this.#request('${ep.method}', \`${pathExpr}\`${hasBody ? ', body' : ''}); }`);
|
|
90
|
+
}
|
|
91
|
+
lines.push(`}`);
|
|
92
|
+
return lines.join('\n');
|
|
93
|
+
}
|
|
94
|
+
// ── Python ────────────────────────────────────────────────────────────────
|
|
95
|
+
function generatePython(name, spec) {
|
|
96
|
+
const lines = [];
|
|
97
|
+
lines.push(`"""Auto-generated API client for '${name}'"""\n`);
|
|
98
|
+
lines.push(`import requests`);
|
|
99
|
+
lines.push(`from dataclasses import dataclass`);
|
|
100
|
+
lines.push(`from typing import Optional, List, Any\n`);
|
|
101
|
+
for (const asset of spec.assets ?? []) {
|
|
102
|
+
lines.push(`@dataclass`);
|
|
103
|
+
lines.push(`class ${pascal(asset.name)}:`);
|
|
104
|
+
if (!asset.fields?.length) {
|
|
105
|
+
lines.push(` pass\n`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
for (const f of asset.fields) {
|
|
109
|
+
lines.push(` ${snake(f.name)}: ${mapPy(f.type, f.fieldKind, f.required)}`);
|
|
110
|
+
}
|
|
111
|
+
lines.push('');
|
|
112
|
+
}
|
|
113
|
+
lines.push(`class ${pascal(name)}Client:`);
|
|
114
|
+
lines.push(` def __init__(self, base_url: str, headers: dict = None):`);
|
|
115
|
+
lines.push(` self.base_url = base_url`);
|
|
116
|
+
lines.push(` self.s = requests.Session()`);
|
|
117
|
+
lines.push(` if headers: self.s.headers.update(headers)\n`);
|
|
118
|
+
lines.push(` def _req(self, method, path, **kw):`);
|
|
119
|
+
lines.push(` r = self.s.request(method, f"{self.base_url}{path}", **kw)`);
|
|
120
|
+
lines.push(` r.raise_for_status()`);
|
|
121
|
+
lines.push(` return r.json()\n`);
|
|
122
|
+
for (const ep of spec.endpoints ?? []) {
|
|
123
|
+
const mName = snake(ep.operationId || methodName(ep));
|
|
124
|
+
const pathExpr = ep.path.replace(/:(\w+)/g, '{$1}');
|
|
125
|
+
const hasBody = ep.method !== 'GET' && ep.method !== 'DELETE';
|
|
126
|
+
const params = paramsPy(ep);
|
|
127
|
+
lines.push(` def ${mName}(self${params}):`);
|
|
128
|
+
lines.push(` """${ep.summary || `${ep.method} ${ep.path}`}"""`);
|
|
129
|
+
lines.push(` return self._req("${ep.method}", f"${pathExpr}"${hasBody ? ', json=body' : ''})\n`);
|
|
130
|
+
}
|
|
131
|
+
return lines.join('\n');
|
|
132
|
+
}
|
|
133
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
134
|
+
function pascal(s) {
|
|
135
|
+
return s.replace(/[^a-zA-Z0-9]+/g, ' ').split(' ').filter(Boolean)
|
|
136
|
+
.map(w => w[0].toUpperCase() + w.slice(1)).join('');
|
|
137
|
+
}
|
|
138
|
+
function snake(s) {
|
|
139
|
+
return s.replace(/([a-z])([A-Z])/g, '$1_$2').replace(/[^a-zA-Z0-9]+/g, '_').toLowerCase();
|
|
140
|
+
}
|
|
141
|
+
function methodName(ep) {
|
|
142
|
+
const parts = ep.path.split('/').filter(p => p && !p.startsWith(':'));
|
|
143
|
+
return `${ep.method.toLowerCase()}${pascal(parts[parts.length - 1] || 'resource')}`;
|
|
144
|
+
}
|
|
145
|
+
function paramsTS(ep) {
|
|
146
|
+
const pp = ep.path.match(/:(\w+)/g)?.map(p => `${p.slice(1)}: string`) ?? [];
|
|
147
|
+
if (ep.method !== 'GET' && ep.method !== 'DELETE')
|
|
148
|
+
pp.push('body: any');
|
|
149
|
+
return pp.join(', ');
|
|
150
|
+
}
|
|
151
|
+
function paramsJS(ep) {
|
|
152
|
+
const pp = ep.path.match(/:(\w+)/g)?.map(p => p.slice(1)) ?? [];
|
|
153
|
+
if (ep.method !== 'GET' && ep.method !== 'DELETE')
|
|
154
|
+
pp.push('body');
|
|
155
|
+
return pp.join(', ');
|
|
156
|
+
}
|
|
157
|
+
function paramsPy(ep) {
|
|
158
|
+
const pp = ep.path.match(/:(\w+)/g)?.map(p => `${snake(p.slice(1))}: str`) ?? [];
|
|
159
|
+
if (ep.method !== 'GET' && ep.method !== 'DELETE')
|
|
160
|
+
pp.push('body: dict');
|
|
161
|
+
return pp.length ? ', ' + pp.join(', ') : '';
|
|
162
|
+
}
|
|
163
|
+
function guessReturn(ep, assets) {
|
|
164
|
+
const parts = ep.path.split('/').filter(p => p && !p.startsWith(':'));
|
|
165
|
+
const last = parts[parts.length - 1];
|
|
166
|
+
if (last) {
|
|
167
|
+
const m = assets.find(a => a.name.toLowerCase() === last.toLowerCase() ||
|
|
168
|
+
a.name.toLowerCase() + 's' === last.toLowerCase());
|
|
169
|
+
if (m)
|
|
170
|
+
return ep.method === 'GET' && !ep.path.includes(':') ? `${pascal(m.name)}[]` : pascal(m.name);
|
|
171
|
+
}
|
|
172
|
+
return 'any';
|
|
173
|
+
}
|
|
174
|
+
function mapTS(type, kind) {
|
|
175
|
+
if (kind === 'array' || kind === 'ARRAY')
|
|
176
|
+
return 'any[]';
|
|
177
|
+
if (kind === 'object' || kind === 'OBJECT')
|
|
178
|
+
return 'Record<string, any>';
|
|
179
|
+
const m = {
|
|
180
|
+
string: 'string', text: 'string', email: 'string', url: 'string', uuid: 'string',
|
|
181
|
+
number: 'number', integer: 'number', float: 'number', decimal: 'number',
|
|
182
|
+
boolean: 'boolean', date: 'string', datetime: 'string', timestamp: 'string',
|
|
183
|
+
};
|
|
184
|
+
return m[type.toLowerCase()] || 'any';
|
|
185
|
+
}
|
|
186
|
+
function mapPy(type, kind, req) {
|
|
187
|
+
let t;
|
|
188
|
+
if (kind === 'array' || kind === 'ARRAY')
|
|
189
|
+
t = 'List[Any]';
|
|
190
|
+
else if (kind === 'object' || kind === 'OBJECT')
|
|
191
|
+
t = 'dict';
|
|
192
|
+
else {
|
|
193
|
+
const m = {
|
|
194
|
+
string: 'str', text: 'str', email: 'str', url: 'str', uuid: 'str',
|
|
195
|
+
number: 'int', integer: 'int', float: 'float', decimal: 'float',
|
|
196
|
+
boolean: 'bool', date: 'str', datetime: 'str', timestamp: 'str',
|
|
197
|
+
};
|
|
198
|
+
t = m[type.toLowerCase()] || 'Any';
|
|
199
|
+
}
|
|
200
|
+
return req ? t : `Optional[${t}]`;
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=scaffold.js.map
|