@constructive-io/cli 6.0.5 → 6.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.
- package/commands/auth.d.ts +6 -0
- package/commands/auth.js +207 -0
- package/commands/codegen.js +3 -0
- package/commands/context.d.ts +7 -0
- package/commands/context.js +233 -0
- package/commands/execute.d.ts +6 -0
- package/commands/execute.js +136 -0
- package/commands.js +6 -0
- package/config/config-manager.d.ts +72 -0
- package/config/config-manager.js +280 -0
- package/config/index.d.ts +5 -0
- package/config/index.js +21 -0
- package/config/types.d.ts +46 -0
- package/config/types.js +10 -0
- package/esm/commands/auth.js +202 -0
- package/esm/commands/codegen.js +3 -0
- package/esm/commands/context.js +228 -0
- package/esm/commands/execute.js +98 -0
- package/esm/commands.js +6 -0
- package/esm/config/config-manager.js +229 -0
- package/esm/config/index.js +5 -0
- package/esm/config/types.js +7 -0
- package/esm/sdk/client.js +66 -0
- package/esm/sdk/executor.js +44 -0
- package/esm/sdk/index.js +5 -0
- package/esm/utils/display.js +10 -0
- package/package.json +5 -4
- package/sdk/client.d.ts +33 -0
- package/sdk/client.js +70 -0
- package/sdk/executor.d.ts +21 -0
- package/sdk/executor.js +48 -0
- package/sdk/index.d.ts +5 -0
- package/sdk/index.js +21 -0
- package/utils/display.d.ts +1 -1
- package/utils/display.js +10 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication commands for the CNC execution engine
|
|
3
|
+
*/
|
|
4
|
+
import { CLIOptions, Inquirerer } from 'inquirerer';
|
|
5
|
+
declare const _default: (argv: Partial<Record<string, unknown>>, prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
|
|
6
|
+
export default _default;
|
package/commands/auth.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Authentication commands for the CNC execution engine
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const inquirerer_1 = require("inquirerer");
|
|
10
|
+
const yanse_1 = __importDefault(require("yanse"));
|
|
11
|
+
const config_1 = require("../config");
|
|
12
|
+
const usage = `
|
|
13
|
+
Constructive Authentication:
|
|
14
|
+
|
|
15
|
+
cnc auth <command> [OPTIONS]
|
|
16
|
+
|
|
17
|
+
Commands:
|
|
18
|
+
set-token <token> Set API token for the current context
|
|
19
|
+
status Show authentication status
|
|
20
|
+
logout Remove credentials for the current context
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--context <name> Specify context (defaults to current context)
|
|
24
|
+
--expires <date> Token expiration date (ISO format)
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
cnc auth set-token eyJhbGciOiJIUzI1NiIs...
|
|
28
|
+
cnc auth status
|
|
29
|
+
cnc auth logout
|
|
30
|
+
cnc auth set-token <token> --context my-api
|
|
31
|
+
|
|
32
|
+
--help, -h Show this help message
|
|
33
|
+
`;
|
|
34
|
+
exports.default = async (argv, prompter, _options) => {
|
|
35
|
+
if (argv.help || argv.h) {
|
|
36
|
+
console.log(usage);
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
const { first: subcommand, newArgv } = (0, inquirerer_1.extractFirst)(argv);
|
|
40
|
+
if (!subcommand) {
|
|
41
|
+
const answer = await prompter.prompt(argv, [
|
|
42
|
+
{
|
|
43
|
+
type: 'autocomplete',
|
|
44
|
+
name: 'subcommand',
|
|
45
|
+
message: 'What do you want to do?',
|
|
46
|
+
options: ['set-token', 'status', 'logout'],
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
return handleSubcommand(answer.subcommand, newArgv, prompter);
|
|
50
|
+
}
|
|
51
|
+
return handleSubcommand(subcommand, newArgv, prompter);
|
|
52
|
+
};
|
|
53
|
+
async function handleSubcommand(subcommand, argv, prompter) {
|
|
54
|
+
switch (subcommand) {
|
|
55
|
+
case 'set-token':
|
|
56
|
+
return handleSetToken(argv, prompter);
|
|
57
|
+
case 'status':
|
|
58
|
+
return handleStatus(argv);
|
|
59
|
+
case 'logout':
|
|
60
|
+
return handleLogout(argv, prompter);
|
|
61
|
+
default:
|
|
62
|
+
console.log(usage);
|
|
63
|
+
console.error(yanse_1.default.red(`Unknown subcommand: ${subcommand}`));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function getTargetContext(argv, prompter) {
|
|
68
|
+
if (argv.context && typeof argv.context === 'string') {
|
|
69
|
+
const context = (0, config_1.loadContext)(argv.context);
|
|
70
|
+
if (!context) {
|
|
71
|
+
console.error(yanse_1.default.red(`Context "${argv.context}" not found.`));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
return argv.context;
|
|
75
|
+
}
|
|
76
|
+
const current = (0, config_1.getCurrentContext)();
|
|
77
|
+
if (current) {
|
|
78
|
+
return current.name;
|
|
79
|
+
}
|
|
80
|
+
const contexts = (0, config_1.listContexts)();
|
|
81
|
+
if (contexts.length === 0) {
|
|
82
|
+
console.error(yanse_1.default.red('No contexts configured.'));
|
|
83
|
+
console.log(yanse_1.default.gray('Run "cnc context create <name>" to create one first.'));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const answer = await prompter.prompt(argv, [
|
|
87
|
+
{
|
|
88
|
+
type: 'autocomplete',
|
|
89
|
+
name: 'context',
|
|
90
|
+
message: 'Select context',
|
|
91
|
+
options: contexts.map(c => c.name),
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
return answer.context;
|
|
95
|
+
}
|
|
96
|
+
async function handleSetToken(argv, prompter) {
|
|
97
|
+
const contextName = await getTargetContext(argv, prompter);
|
|
98
|
+
const { first: token, newArgv } = (0, inquirerer_1.extractFirst)(argv);
|
|
99
|
+
let tokenValue = token;
|
|
100
|
+
if (!tokenValue) {
|
|
101
|
+
const answer = await prompter.prompt(newArgv, [
|
|
102
|
+
{
|
|
103
|
+
type: 'password',
|
|
104
|
+
name: 'token',
|
|
105
|
+
message: 'API Token',
|
|
106
|
+
required: true,
|
|
107
|
+
},
|
|
108
|
+
]);
|
|
109
|
+
tokenValue = answer.token;
|
|
110
|
+
}
|
|
111
|
+
if (!tokenValue || tokenValue.trim() === '') {
|
|
112
|
+
console.error(yanse_1.default.red('Token cannot be empty.'));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
const expiresAt = argv.expires;
|
|
116
|
+
(0, config_1.setContextCredentials)(contextName, tokenValue.trim(), { expiresAt });
|
|
117
|
+
console.log(yanse_1.default.green(`Token saved for context: ${contextName}`));
|
|
118
|
+
if (expiresAt) {
|
|
119
|
+
console.log(yanse_1.default.gray(`Expires: ${expiresAt}`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function handleStatus(argv) {
|
|
123
|
+
const settings = (0, config_1.loadSettings)();
|
|
124
|
+
const contexts = (0, config_1.listContexts)();
|
|
125
|
+
if (contexts.length === 0) {
|
|
126
|
+
console.log(yanse_1.default.gray('No contexts configured.'));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (argv.context && typeof argv.context === 'string') {
|
|
130
|
+
const context = (0, config_1.loadContext)(argv.context);
|
|
131
|
+
if (!context) {
|
|
132
|
+
console.error(yanse_1.default.red(`Context "${argv.context}" not found.`));
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
showContextAuthStatus(context.name, settings.currentContext === context.name);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
console.log(yanse_1.default.bold('Authentication Status:'));
|
|
139
|
+
console.log();
|
|
140
|
+
for (const context of contexts) {
|
|
141
|
+
const isCurrent = context.name === settings.currentContext;
|
|
142
|
+
showContextAuthStatus(context.name, isCurrent);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function showContextAuthStatus(contextName, isCurrent) {
|
|
146
|
+
const creds = (0, config_1.getContextCredentials)(contextName);
|
|
147
|
+
const hasAuth = (0, config_1.hasValidCredentials)(contextName);
|
|
148
|
+
const marker = isCurrent ? yanse_1.default.green('*') : ' ';
|
|
149
|
+
console.log(`${marker} ${yanse_1.default.bold(contextName)}`);
|
|
150
|
+
if (hasAuth && creds) {
|
|
151
|
+
console.log(` Status: ${yanse_1.default.green('Authenticated')}`);
|
|
152
|
+
console.log(` Token: ${maskToken(creds.token)}`);
|
|
153
|
+
if (creds.expiresAt) {
|
|
154
|
+
const expiresAt = new Date(creds.expiresAt);
|
|
155
|
+
const now = new Date();
|
|
156
|
+
if (expiresAt <= now) {
|
|
157
|
+
console.log(` Expires: ${yanse_1.default.red(creds.expiresAt + ' (expired)')}`);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log(` Expires: ${creds.expiresAt}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if (creds && creds.token) {
|
|
165
|
+
console.log(` Status: ${yanse_1.default.red('Expired')}`);
|
|
166
|
+
console.log(` Token: ${maskToken(creds.token)}`);
|
|
167
|
+
if (creds.expiresAt) {
|
|
168
|
+
console.log(` Expired: ${creds.expiresAt}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.log(` Status: ${yanse_1.default.yellow('Not authenticated')}`);
|
|
173
|
+
}
|
|
174
|
+
console.log();
|
|
175
|
+
}
|
|
176
|
+
function maskToken(token) {
|
|
177
|
+
if (token.length <= 10) {
|
|
178
|
+
return '****';
|
|
179
|
+
}
|
|
180
|
+
return token.substring(0, 6) + '...' + token.substring(token.length - 4);
|
|
181
|
+
}
|
|
182
|
+
async function handleLogout(argv, prompter) {
|
|
183
|
+
const contextName = await getTargetContext(argv, prompter);
|
|
184
|
+
const creds = (0, config_1.getContextCredentials)(contextName);
|
|
185
|
+
if (!creds) {
|
|
186
|
+
console.log(yanse_1.default.gray(`No credentials found for context: ${contextName}`));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const confirm = await prompter.prompt(argv, [
|
|
190
|
+
{
|
|
191
|
+
type: 'confirm',
|
|
192
|
+
name: 'confirm',
|
|
193
|
+
message: `Remove credentials for context "${contextName}"?`,
|
|
194
|
+
default: false,
|
|
195
|
+
},
|
|
196
|
+
]);
|
|
197
|
+
if (!confirm.confirm) {
|
|
198
|
+
console.log(yanse_1.default.gray('Cancelled.'));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if ((0, config_1.removeContextCredentials)(contextName)) {
|
|
202
|
+
console.log(yanse_1.default.green(`Credentials removed for context: ${contextName}`));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
console.log(yanse_1.default.gray(`No credentials found for context: ${contextName}`));
|
|
206
|
+
}
|
|
207
|
+
}
|
package/commands/codegen.js
CHANGED
|
@@ -20,6 +20,8 @@ Generator Options:
|
|
|
20
20
|
--orm Generate ORM client
|
|
21
21
|
--output <dir> Output directory (default: codegen)
|
|
22
22
|
--authorization <token> Authorization header value
|
|
23
|
+
--browserCompatible Generate browser-compatible code (default: true)
|
|
24
|
+
Set to false for Node.js with localhost DNS fix
|
|
23
25
|
--dryRun Preview without writing files
|
|
24
26
|
--verbose Verbose output
|
|
25
27
|
|
|
@@ -53,6 +55,7 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
53
55
|
authorization: answers.authorization,
|
|
54
56
|
reactQuery: answers.reactQuery,
|
|
55
57
|
orm: answers.orm,
|
|
58
|
+
browserCompatible: answers.browserCompatible,
|
|
56
59
|
dryRun: answers.dryRun,
|
|
57
60
|
verbose: answers.verbose,
|
|
58
61
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context management commands for the CNC execution engine
|
|
3
|
+
* Similar to kubectl contexts - manages named endpoint + credential configurations
|
|
4
|
+
*/
|
|
5
|
+
import { CLIOptions, Inquirerer } from 'inquirerer';
|
|
6
|
+
declare const _default: (argv: Partial<Record<string, unknown>>, prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Context management commands for the CNC execution engine
|
|
4
|
+
* Similar to kubectl contexts - manages named endpoint + credential configurations
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const inquirerer_1 = require("inquirerer");
|
|
11
|
+
const yanse_1 = __importDefault(require("yanse"));
|
|
12
|
+
const config_1 = require("../config");
|
|
13
|
+
const usage = `
|
|
14
|
+
Constructive Context Management:
|
|
15
|
+
|
|
16
|
+
cnc context <command> [OPTIONS]
|
|
17
|
+
|
|
18
|
+
Commands:
|
|
19
|
+
create <name> Create a new context
|
|
20
|
+
list List all contexts
|
|
21
|
+
use <name> Set the active context
|
|
22
|
+
current Show current context
|
|
23
|
+
delete <name> Delete a context
|
|
24
|
+
|
|
25
|
+
Create Options:
|
|
26
|
+
--endpoint <url> GraphQL endpoint URL
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
cnc context create my-api --endpoint https://api.example.com/graphql
|
|
30
|
+
cnc context list
|
|
31
|
+
cnc context use my-api
|
|
32
|
+
cnc context current
|
|
33
|
+
cnc context delete my-api
|
|
34
|
+
|
|
35
|
+
--help, -h Show this help message
|
|
36
|
+
`;
|
|
37
|
+
exports.default = async (argv, prompter, _options) => {
|
|
38
|
+
if (argv.help || argv.h) {
|
|
39
|
+
console.log(usage);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
const { first: subcommand, newArgv } = (0, inquirerer_1.extractFirst)(argv);
|
|
43
|
+
if (!subcommand) {
|
|
44
|
+
const answer = await prompter.prompt(argv, [
|
|
45
|
+
{
|
|
46
|
+
type: 'autocomplete',
|
|
47
|
+
name: 'subcommand',
|
|
48
|
+
message: 'What do you want to do?',
|
|
49
|
+
options: ['create', 'list', 'use', 'current', 'delete'],
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
return handleSubcommand(answer.subcommand, newArgv, prompter);
|
|
53
|
+
}
|
|
54
|
+
return handleSubcommand(subcommand, newArgv, prompter);
|
|
55
|
+
};
|
|
56
|
+
async function handleSubcommand(subcommand, argv, prompter) {
|
|
57
|
+
switch (subcommand) {
|
|
58
|
+
case 'create':
|
|
59
|
+
return handleCreate(argv, prompter);
|
|
60
|
+
case 'list':
|
|
61
|
+
return handleList();
|
|
62
|
+
case 'use':
|
|
63
|
+
return handleUse(argv, prompter);
|
|
64
|
+
case 'current':
|
|
65
|
+
return handleCurrent();
|
|
66
|
+
case 'delete':
|
|
67
|
+
return handleDelete(argv, prompter);
|
|
68
|
+
default:
|
|
69
|
+
console.log(usage);
|
|
70
|
+
console.error(yanse_1.default.red(`Unknown subcommand: ${subcommand}`));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function handleCreate(argv, prompter) {
|
|
75
|
+
const { first: name, newArgv } = (0, inquirerer_1.extractFirst)(argv);
|
|
76
|
+
const settings = (0, config_1.loadSettings)();
|
|
77
|
+
const answers = await prompter.prompt({ name, ...newArgv }, [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
name: 'name',
|
|
81
|
+
message: 'Context name',
|
|
82
|
+
required: true,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: 'text',
|
|
86
|
+
name: 'endpoint',
|
|
87
|
+
message: 'GraphQL endpoint URL',
|
|
88
|
+
required: true,
|
|
89
|
+
},
|
|
90
|
+
]);
|
|
91
|
+
const answersRecord = answers;
|
|
92
|
+
const contextName = answersRecord.name;
|
|
93
|
+
const endpoint = answersRecord.endpoint;
|
|
94
|
+
const existing = (0, config_1.loadContext)(contextName);
|
|
95
|
+
if (existing) {
|
|
96
|
+
console.error(yanse_1.default.red(`Context "${contextName}" already exists.`));
|
|
97
|
+
console.log(yanse_1.default.gray(`Use "cnc context delete ${contextName}" to remove it first.`));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
const context = (0, config_1.createContext)(contextName, endpoint);
|
|
101
|
+
if (!settings.currentContext) {
|
|
102
|
+
(0, config_1.setCurrentContext)(contextName);
|
|
103
|
+
console.log(yanse_1.default.green(`Created and activated context: ${contextName}`));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
console.log(yanse_1.default.green(`Created context: ${contextName}`));
|
|
107
|
+
}
|
|
108
|
+
console.log();
|
|
109
|
+
console.log(` Endpoint: ${context.endpoint}`);
|
|
110
|
+
console.log();
|
|
111
|
+
console.log(yanse_1.default.gray(`Next: Run "cnc auth set-token <token>" to configure authentication.`));
|
|
112
|
+
}
|
|
113
|
+
function handleList() {
|
|
114
|
+
const contexts = (0, config_1.listContexts)();
|
|
115
|
+
const settings = (0, config_1.loadSettings)();
|
|
116
|
+
if (contexts.length === 0) {
|
|
117
|
+
console.log(yanse_1.default.gray('No contexts configured.'));
|
|
118
|
+
console.log(yanse_1.default.gray('Run "cnc context create <name>" to create one.'));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
console.log(yanse_1.default.bold('Contexts:'));
|
|
122
|
+
console.log();
|
|
123
|
+
for (const context of contexts) {
|
|
124
|
+
const isCurrent = context.name === settings.currentContext;
|
|
125
|
+
const hasAuth = (0, config_1.hasValidCredentials)(context.name);
|
|
126
|
+
const marker = isCurrent ? yanse_1.default.green('*') : ' ';
|
|
127
|
+
const authStatus = hasAuth ? yanse_1.default.green('[authenticated]') : yanse_1.default.yellow('[no token]');
|
|
128
|
+
console.log(`${marker} ${yanse_1.default.bold(context.name)} ${authStatus}`);
|
|
129
|
+
console.log(` Endpoint: ${context.endpoint}`);
|
|
130
|
+
console.log();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function handleUse(argv, prompter) {
|
|
134
|
+
const { first: name } = (0, inquirerer_1.extractFirst)(argv);
|
|
135
|
+
const contexts = (0, config_1.listContexts)();
|
|
136
|
+
if (contexts.length === 0) {
|
|
137
|
+
console.log(yanse_1.default.gray('No contexts configured.'));
|
|
138
|
+
console.log(yanse_1.default.gray('Run "cnc context create <name>" to create one.'));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
let contextName = name;
|
|
142
|
+
if (!contextName) {
|
|
143
|
+
const answer = await prompter.prompt(argv, [
|
|
144
|
+
{
|
|
145
|
+
type: 'autocomplete',
|
|
146
|
+
name: 'name',
|
|
147
|
+
message: 'Select context',
|
|
148
|
+
options: contexts.map(c => c.name),
|
|
149
|
+
},
|
|
150
|
+
]);
|
|
151
|
+
contextName = answer.name;
|
|
152
|
+
}
|
|
153
|
+
if ((0, config_1.setCurrentContext)(contextName)) {
|
|
154
|
+
console.log(yanse_1.default.green(`Switched to context: ${contextName}`));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.error(yanse_1.default.red(`Context "${contextName}" not found.`));
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function handleCurrent() {
|
|
162
|
+
const current = (0, config_1.getCurrentContext)();
|
|
163
|
+
if (!current) {
|
|
164
|
+
console.log(yanse_1.default.gray('No current context set.'));
|
|
165
|
+
console.log(yanse_1.default.gray('Run "cnc context use <name>" to set one.'));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const creds = (0, config_1.getContextCredentials)(current.name);
|
|
169
|
+
const hasAuth = (0, config_1.hasValidCredentials)(current.name);
|
|
170
|
+
console.log();
|
|
171
|
+
console.log(yanse_1.default.bold(`Current context: ${current.name}`));
|
|
172
|
+
console.log();
|
|
173
|
+
console.log(` Endpoint: ${current.endpoint}`);
|
|
174
|
+
console.log(` Created: ${current.createdAt}`);
|
|
175
|
+
console.log(` Updated: ${current.updatedAt}`);
|
|
176
|
+
console.log();
|
|
177
|
+
console.log(yanse_1.default.bold('Authentication:'));
|
|
178
|
+
if (hasAuth) {
|
|
179
|
+
console.log(` Status: ${yanse_1.default.green('Authenticated')}`);
|
|
180
|
+
if (creds?.expiresAt) {
|
|
181
|
+
console.log(` Expires: ${creds.expiresAt}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.log(` Status: ${yanse_1.default.yellow('Not authenticated')}`);
|
|
186
|
+
console.log(yanse_1.default.gray(` Run "cnc auth set-token <token>" to configure.`));
|
|
187
|
+
}
|
|
188
|
+
console.log();
|
|
189
|
+
}
|
|
190
|
+
async function handleDelete(argv, prompter) {
|
|
191
|
+
const { first: name } = (0, inquirerer_1.extractFirst)(argv);
|
|
192
|
+
const contexts = (0, config_1.listContexts)();
|
|
193
|
+
if (contexts.length === 0) {
|
|
194
|
+
console.log(yanse_1.default.gray('No contexts configured.'));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
let contextName = name;
|
|
198
|
+
if (!contextName) {
|
|
199
|
+
const answer = await prompter.prompt(argv, [
|
|
200
|
+
{
|
|
201
|
+
type: 'autocomplete',
|
|
202
|
+
name: 'name',
|
|
203
|
+
message: 'Select context to delete',
|
|
204
|
+
options: contexts.map(c => c.name),
|
|
205
|
+
},
|
|
206
|
+
]);
|
|
207
|
+
contextName = answer.name;
|
|
208
|
+
}
|
|
209
|
+
const confirm = await prompter.prompt(argv, [
|
|
210
|
+
{
|
|
211
|
+
type: 'confirm',
|
|
212
|
+
name: 'confirm',
|
|
213
|
+
message: `Are you sure you want to delete context "${contextName}"?`,
|
|
214
|
+
default: false,
|
|
215
|
+
},
|
|
216
|
+
]);
|
|
217
|
+
if (!confirm.confirm) {
|
|
218
|
+
console.log(yanse_1.default.gray('Cancelled.'));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if ((0, config_1.deleteContext)(contextName)) {
|
|
222
|
+
const settings = (0, config_1.loadSettings)();
|
|
223
|
+
if (settings.currentContext === contextName) {
|
|
224
|
+
settings.currentContext = undefined;
|
|
225
|
+
(0, config_1.saveSettings)(settings);
|
|
226
|
+
}
|
|
227
|
+
console.log(yanse_1.default.green(`Deleted context: ${contextName}`));
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
console.error(yanse_1.default.red(`Context "${contextName}" not found.`));
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Execute command for running GraphQL queries
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const yanse_1 = __importDefault(require("yanse"));
|
|
44
|
+
const sdk_1 = require("../sdk");
|
|
45
|
+
const usage = `
|
|
46
|
+
Constructive Execute - Run GraphQL Queries:
|
|
47
|
+
|
|
48
|
+
cnc execute [OPTIONS]
|
|
49
|
+
|
|
50
|
+
Options:
|
|
51
|
+
--query <graphql> GraphQL query/mutation string
|
|
52
|
+
--file <path> Path to file containing GraphQL query
|
|
53
|
+
--variables <json> Variables as JSON string
|
|
54
|
+
--context <name> Context to use (defaults to current)
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
# Execute inline query
|
|
58
|
+
cnc execute --query 'query { databases { nodes { id name } } }'
|
|
59
|
+
|
|
60
|
+
# Execute from file
|
|
61
|
+
cnc execute --file query.graphql
|
|
62
|
+
|
|
63
|
+
# With variables
|
|
64
|
+
cnc execute --query 'query($id: UUID!) { database(id: $id) { name } }' --variables '{"id":"..."}'
|
|
65
|
+
|
|
66
|
+
--help, -h Show this help message
|
|
67
|
+
`;
|
|
68
|
+
exports.default = async (argv, prompter, _options) => {
|
|
69
|
+
if (argv.help || argv.h) {
|
|
70
|
+
console.log(usage);
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
let query;
|
|
74
|
+
let variables;
|
|
75
|
+
if (argv.file) {
|
|
76
|
+
const filePath = argv.file;
|
|
77
|
+
if (!fs.existsSync(filePath)) {
|
|
78
|
+
console.error(yanse_1.default.red(`File not found: ${filePath}`));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
query = fs.readFileSync(filePath, 'utf8');
|
|
82
|
+
}
|
|
83
|
+
else if (argv.query) {
|
|
84
|
+
query = argv.query;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const answers = await prompter.prompt(argv, [
|
|
88
|
+
{
|
|
89
|
+
type: 'text',
|
|
90
|
+
name: 'query',
|
|
91
|
+
message: 'GraphQL query',
|
|
92
|
+
required: true,
|
|
93
|
+
},
|
|
94
|
+
]);
|
|
95
|
+
query = answers.query;
|
|
96
|
+
}
|
|
97
|
+
if (argv.variables) {
|
|
98
|
+
try {
|
|
99
|
+
variables = JSON.parse(argv.variables);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
console.error(yanse_1.default.red('Invalid JSON in --variables'));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
let execContext;
|
|
107
|
+
try {
|
|
108
|
+
execContext = await (0, sdk_1.getExecutionContext)(argv.context);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error(yanse_1.default.red(error instanceof Error ? error.message : 'Failed to get execution context'));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
console.log(yanse_1.default.gray(`Context: ${execContext.context.name}`));
|
|
115
|
+
console.log(yanse_1.default.gray(`Endpoint: ${execContext.context.endpoint}`));
|
|
116
|
+
console.log();
|
|
117
|
+
const result = await (0, sdk_1.execute)(query, variables, execContext);
|
|
118
|
+
if (result.ok) {
|
|
119
|
+
console.log(yanse_1.default.green('Success!'));
|
|
120
|
+
console.log();
|
|
121
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.error(yanse_1.default.red('Failed!'));
|
|
125
|
+
console.log();
|
|
126
|
+
if (result.errors) {
|
|
127
|
+
for (const error of result.errors) {
|
|
128
|
+
console.error(yanse_1.default.red(` - ${error.message}`));
|
|
129
|
+
if (error.path) {
|
|
130
|
+
console.error(yanse_1.default.gray(` Path: ${error.path.join('.')}`));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
};
|
package/commands.js
CHANGED
|
@@ -6,7 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.commands = void 0;
|
|
7
7
|
const utils_1 = require("@inquirerer/utils");
|
|
8
8
|
const inquirerer_1 = require("inquirerer");
|
|
9
|
+
const auth_1 = __importDefault(require("./commands/auth"));
|
|
9
10
|
const codegen_1 = __importDefault(require("./commands/codegen"));
|
|
11
|
+
const context_1 = __importDefault(require("./commands/context"));
|
|
12
|
+
const execute_1 = __importDefault(require("./commands/execute"));
|
|
10
13
|
const explorer_1 = __importDefault(require("./commands/explorer"));
|
|
11
14
|
const get_graphql_schema_1 = __importDefault(require("./commands/get-graphql-schema"));
|
|
12
15
|
const jobs_1 = __importDefault(require("./commands/jobs"));
|
|
@@ -19,6 +22,9 @@ const createCommandMap = () => {
|
|
|
19
22
|
'get-graphql-schema': get_graphql_schema_1.default,
|
|
20
23
|
codegen: codegen_1.default,
|
|
21
24
|
jobs: jobs_1.default,
|
|
25
|
+
context: context_1.default,
|
|
26
|
+
auth: auth_1.default,
|
|
27
|
+
execute: execute_1.default,
|
|
22
28
|
};
|
|
23
29
|
};
|
|
24
30
|
const commands = async (argv, prompter, options) => {
|