@ductape/cli 0.2.2 → 0.2.4
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/commands/cloud.d.ts +5 -1
- package/dist/commands/cloud.js +18 -1
- package/dist/index.js +10 -1
- package/dist/lib/output.js +19 -5
- package/dist/lib/platform-api.d.ts +6 -0
- package/dist/lib/platform-api.js +11 -0
- package/package.json +1 -1
- package/src/commands/cloud.ts +21 -3
- package/src/index.ts +11 -1
- package/src/lib/output.ts +20 -5
- package/src/lib/platform-api.ts +17 -0
package/dist/commands/cloud.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
type CloudTarget = 'connections' | 'resources';
|
|
1
|
+
type CloudTarget = 'connections' | 'resources' | 'tiers';
|
|
2
2
|
export declare function runCloud(target: CloudTarget, verb: string, opts: {
|
|
3
3
|
id?: string;
|
|
4
4
|
file?: string;
|
|
5
|
+
provider?: string;
|
|
6
|
+
type?: string;
|
|
7
|
+
dbType?: string;
|
|
8
|
+
tier?: string;
|
|
5
9
|
json?: boolean;
|
|
6
10
|
}, extraArgs: string[]): Promise<void>;
|
|
7
11
|
export {};
|
package/dist/commands/cloud.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { readJsonBody } from '../lib/read-body.js';
|
|
2
2
|
import { getSdkProxy, requireSession } from '../lib/proxy/context.js';
|
|
3
3
|
import { printJson } from '../lib/output.js';
|
|
4
|
+
import { listCloudTiers } from '../lib/platform-api.js';
|
|
5
|
+
import { requireWorkspaceContext } from '../lib/workspace-context.js';
|
|
4
6
|
export async function runCloud(target, verb, opts, extraArgs) {
|
|
7
|
+
if (target === 'tiers') {
|
|
8
|
+
const ctx = requireWorkspaceContext();
|
|
9
|
+
const result = await listCloudTiers(ctx, {
|
|
10
|
+
provider: opts.provider,
|
|
11
|
+
resource_type: opts.type,
|
|
12
|
+
db_type: opts.dbType,
|
|
13
|
+
});
|
|
14
|
+
printJson(result, Boolean(opts.json));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
5
17
|
requireSession();
|
|
6
18
|
const proxy = getSdkProxy();
|
|
7
|
-
|
|
19
|
+
let body = readJsonBody(opts.file);
|
|
20
|
+
if (opts.tier) {
|
|
21
|
+
body = { ...(body && typeof body === 'object' && !Array.isArray(body) ? body : {}), tier: opts.tier };
|
|
22
|
+
}
|
|
8
23
|
const id = opts.id ?? extraArgs[0];
|
|
9
24
|
let method;
|
|
10
25
|
let params;
|
|
@@ -30,7 +45,9 @@ export async function runCloud(target, verb, opts, extraArgs) {
|
|
|
30
45
|
import: ['resources.import', [body]],
|
|
31
46
|
provision: ['resources.provision', [body]],
|
|
32
47
|
'import-persist': ['resources.importAndPersist', [body]],
|
|
48
|
+
'import-persist-all': ['resources.importAndPersistAll', [body]],
|
|
33
49
|
'provision-persist': ['resources.provisionAndPersist', [body]],
|
|
50
|
+
'provision-persist-all': ['resources.provisionAndPersistAll', [body]],
|
|
34
51
|
};
|
|
35
52
|
const entry = map[verb.toLowerCase()];
|
|
36
53
|
if (!entry)
|
package/dist/index.js
CHANGED
|
@@ -249,8 +249,17 @@ cloud
|
|
|
249
249
|
cloud
|
|
250
250
|
.command('resources <verb>')
|
|
251
251
|
.option('-f, --file <path>')
|
|
252
|
+
.option('--tier <name>', 'Tier name from `cloud tiers list` (e.g. db.t3.micro, Standard_B1ms, M0)')
|
|
252
253
|
.option('--json', 'JSON output')
|
|
253
|
-
.action(wrap((verb, opts) => runCloud('resources', verb, { file: opts.file, json: opts.json }, [])));
|
|
254
|
+
.action(wrap((verb, opts) => runCloud('resources', verb, { file: opts.file, tier: opts.tier, json: opts.json }, [])));
|
|
255
|
+
cloud
|
|
256
|
+
.command('tiers')
|
|
257
|
+
.description('List available cloud resource tiers and estimated costs')
|
|
258
|
+
.option('--provider <name>', 'Filter by provider: aws, gcp, azure, mongodb_atlas, neo4j_aura')
|
|
259
|
+
.option('--type <resource_type>', 'Filter by resource type: database, storage, graph')
|
|
260
|
+
.option('--db-type <db_type>', 'Filter by database type: postgresql, mysql, mongodb, dynamodb, neo4j')
|
|
261
|
+
.option('--json', 'JSON output')
|
|
262
|
+
.action(wrap((opts) => runCloud('tiers', 'list', { provider: opts.provider, type: opts.type, dbType: opts.dbType, json: opts.json }, [])));
|
|
254
263
|
const db = program.command('db').description('Database runtime (db-proxy)');
|
|
255
264
|
db.command('context').option('--json', 'JSON output').action(wrap((opts) => runDbContext(Boolean(opts.json))));
|
|
256
265
|
const dbMigrate = db
|
package/dist/lib/output.js
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
+
const REDACTED_KEYS = new Set(['private_key']);
|
|
2
|
+
function redactSensitiveFields(data) {
|
|
3
|
+
if (Array.isArray(data))
|
|
4
|
+
return data.map(redactSensitiveFields);
|
|
5
|
+
if (data !== null && typeof data === 'object') {
|
|
6
|
+
const result = {};
|
|
7
|
+
for (const [key, value] of Object.entries(data)) {
|
|
8
|
+
result[key] = REDACTED_KEYS.has(key) ? '[REDACTED]' : redactSensitiveFields(value);
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
1
14
|
export function printJson(data, jsonMode) {
|
|
15
|
+
const safe = redactSensitiveFields(data);
|
|
2
16
|
if (jsonMode) {
|
|
3
|
-
console.log(JSON.stringify(
|
|
17
|
+
console.log(JSON.stringify(safe, null, 2));
|
|
4
18
|
return;
|
|
5
19
|
}
|
|
6
|
-
if (
|
|
20
|
+
if (safe === undefined || safe === null) {
|
|
7
21
|
console.log('(no data)');
|
|
8
22
|
return;
|
|
9
23
|
}
|
|
10
|
-
if (typeof
|
|
11
|
-
console.log(JSON.stringify(
|
|
24
|
+
if (typeof safe === 'object') {
|
|
25
|
+
console.log(JSON.stringify(safe, null, 2));
|
|
12
26
|
return;
|
|
13
27
|
}
|
|
14
|
-
console.log(String(
|
|
28
|
+
console.log(String(safe));
|
|
15
29
|
}
|
|
16
30
|
export function success(message) {
|
|
17
31
|
console.log(`✓ ${message}`);
|
|
@@ -17,3 +17,9 @@ export declare function createApp(ctx: WorkspaceContext, body: Record<string, un
|
|
|
17
17
|
export declare function updateApp(ctx: WorkspaceContext, appId: string, body: Record<string, unknown>): Promise<unknown>;
|
|
18
18
|
export declare function updateAppViaProxy(ctx: WorkspaceContext, tag: string, body: Record<string, unknown>): Promise<unknown>;
|
|
19
19
|
export declare function deleteApp(ctx: WorkspaceContext, appId: string): Promise<unknown>;
|
|
20
|
+
export interface TierQuery {
|
|
21
|
+
provider?: string;
|
|
22
|
+
resource_type?: string;
|
|
23
|
+
db_type?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function listCloudTiers(ctx: WorkspaceContext, q: TierQuery): Promise<unknown[]>;
|
package/dist/lib/platform-api.js
CHANGED
|
@@ -135,3 +135,14 @@ export async function deleteApp(ctx, appId) {
|
|
|
135
135
|
};
|
|
136
136
|
return client(ctx).delete(`/apps/v1/${appId}?${new URLSearchParams(q).toString()}`);
|
|
137
137
|
}
|
|
138
|
+
export async function listCloudTiers(ctx, q) {
|
|
139
|
+
const params = workspaceAuthQuery(ctx);
|
|
140
|
+
if (q.provider)
|
|
141
|
+
params.provider = q.provider;
|
|
142
|
+
if (q.resource_type)
|
|
143
|
+
params.resource_type = q.resource_type;
|
|
144
|
+
if (q.db_type)
|
|
145
|
+
params.db_type = q.db_type;
|
|
146
|
+
const result = await client(ctx).getPath('/integrations/v1/cloud/tiers', params);
|
|
147
|
+
return unwrapList(result);
|
|
148
|
+
}
|
package/package.json
CHANGED
package/src/commands/cloud.ts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import { readJsonBody } from '../lib/read-body.js';
|
|
2
2
|
import { getSdkProxy, requireSession } from '../lib/proxy/context.js';
|
|
3
3
|
import { printJson } from '../lib/output.js';
|
|
4
|
+
import { listCloudTiers } from '../lib/platform-api.js';
|
|
5
|
+
import { requireWorkspaceContext } from '../lib/workspace-context.js';
|
|
4
6
|
|
|
5
|
-
type CloudTarget = 'connections' | 'resources';
|
|
7
|
+
type CloudTarget = 'connections' | 'resources' | 'tiers';
|
|
6
8
|
|
|
7
9
|
export async function runCloud(
|
|
8
10
|
target: CloudTarget,
|
|
9
11
|
verb: string,
|
|
10
|
-
opts: { id?: string; file?: string; json?: boolean },
|
|
12
|
+
opts: { id?: string; file?: string; provider?: string; type?: string; dbType?: string; tier?: string; json?: boolean },
|
|
11
13
|
extraArgs: string[],
|
|
12
14
|
): Promise<void> {
|
|
15
|
+
if (target === 'tiers') {
|
|
16
|
+
const ctx = requireWorkspaceContext();
|
|
17
|
+
const result = await listCloudTiers(ctx, {
|
|
18
|
+
provider: opts.provider,
|
|
19
|
+
resource_type: opts.type,
|
|
20
|
+
db_type: opts.dbType,
|
|
21
|
+
});
|
|
22
|
+
printJson(result, Boolean(opts.json));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
requireSession();
|
|
14
27
|
const proxy = getSdkProxy();
|
|
15
|
-
|
|
28
|
+
let body = readJsonBody(opts.file);
|
|
29
|
+
if (opts.tier) {
|
|
30
|
+
body = { ...(body && typeof body === 'object' && !Array.isArray(body) ? body as Record<string, unknown> : {}), tier: opts.tier };
|
|
31
|
+
}
|
|
16
32
|
const id = opts.id ?? extraArgs[0];
|
|
17
33
|
|
|
18
34
|
let method: string;
|
|
@@ -38,7 +54,9 @@ export async function runCloud(
|
|
|
38
54
|
import: ['resources.import', [body]],
|
|
39
55
|
provision: ['resources.provision', [body]],
|
|
40
56
|
'import-persist': ['resources.importAndPersist', [body]],
|
|
57
|
+
'import-persist-all': ['resources.importAndPersistAll', [body]],
|
|
41
58
|
'provision-persist': ['resources.provisionAndPersist', [body]],
|
|
59
|
+
'provision-persist-all': ['resources.provisionAndPersistAll', [body]],
|
|
42
60
|
};
|
|
43
61
|
const entry = map[verb.toLowerCase()];
|
|
44
62
|
if (!entry) throw new Error(`Unknown cloud resources verb: ${verb}`);
|
package/src/index.ts
CHANGED
|
@@ -326,8 +326,18 @@ cloud
|
|
|
326
326
|
cloud
|
|
327
327
|
.command('resources <verb>')
|
|
328
328
|
.option('-f, --file <path>')
|
|
329
|
+
.option('--tier <name>', 'Tier name from `cloud tiers list` (e.g. db.t3.micro, Standard_B1ms, M0)')
|
|
329
330
|
.option('--json', 'JSON output')
|
|
330
|
-
.action(wrap((verb: string, opts) => runCloud('resources', verb, { file: opts.file, json: opts.json }, [])));
|
|
331
|
+
.action(wrap((verb: string, opts) => runCloud('resources', verb, { file: opts.file, tier: opts.tier, json: opts.json }, [])));
|
|
332
|
+
|
|
333
|
+
cloud
|
|
334
|
+
.command('tiers')
|
|
335
|
+
.description('List available cloud resource tiers and estimated costs')
|
|
336
|
+
.option('--provider <name>', 'Filter by provider: aws, gcp, azure, mongodb_atlas, neo4j_aura')
|
|
337
|
+
.option('--type <resource_type>', 'Filter by resource type: database, storage, graph')
|
|
338
|
+
.option('--db-type <db_type>', 'Filter by database type: postgresql, mysql, mongodb, dynamodb, neo4j')
|
|
339
|
+
.option('--json', 'JSON output')
|
|
340
|
+
.action(wrap((opts) => runCloud('tiers', 'list', { provider: opts.provider, type: opts.type, dbType: opts.dbType, json: opts.json }, [])));
|
|
331
341
|
|
|
332
342
|
const db = program.command('db').description('Database runtime (db-proxy)');
|
|
333
343
|
|
package/src/lib/output.ts
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
|
+
const REDACTED_KEYS = new Set(['private_key']);
|
|
2
|
+
|
|
3
|
+
function redactSensitiveFields(data: unknown): unknown {
|
|
4
|
+
if (Array.isArray(data)) return data.map(redactSensitiveFields);
|
|
5
|
+
if (data !== null && typeof data === 'object') {
|
|
6
|
+
const result: Record<string, unknown> = {};
|
|
7
|
+
for (const [key, value] of Object.entries(data as Record<string, unknown>)) {
|
|
8
|
+
result[key] = REDACTED_KEYS.has(key) ? '[REDACTED]' : redactSensitiveFields(value);
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
export function printJson(data: unknown, jsonMode: boolean): void {
|
|
16
|
+
const safe = redactSensitiveFields(data);
|
|
2
17
|
if (jsonMode) {
|
|
3
|
-
console.log(JSON.stringify(
|
|
18
|
+
console.log(JSON.stringify(safe, null, 2));
|
|
4
19
|
return;
|
|
5
20
|
}
|
|
6
|
-
if (
|
|
21
|
+
if (safe === undefined || safe === null) {
|
|
7
22
|
console.log('(no data)');
|
|
8
23
|
return;
|
|
9
24
|
}
|
|
10
|
-
if (typeof
|
|
11
|
-
console.log(JSON.stringify(
|
|
25
|
+
if (typeof safe === 'object') {
|
|
26
|
+
console.log(JSON.stringify(safe, null, 2));
|
|
12
27
|
return;
|
|
13
28
|
}
|
|
14
|
-
console.log(String(
|
|
29
|
+
console.log(String(safe));
|
|
15
30
|
}
|
|
16
31
|
|
|
17
32
|
export function success(message: string): void {
|
package/src/lib/platform-api.ts
CHANGED
|
@@ -190,3 +190,20 @@ export async function deleteApp(ctx: WorkspaceContext, appId: string): Promise<u
|
|
|
190
190
|
`/apps/v1/${appId}?${new URLSearchParams(q).toString()}`,
|
|
191
191
|
);
|
|
192
192
|
}
|
|
193
|
+
|
|
194
|
+
// —— Cloud tiers ——
|
|
195
|
+
|
|
196
|
+
export interface TierQuery {
|
|
197
|
+
provider?: string;
|
|
198
|
+
resource_type?: string;
|
|
199
|
+
db_type?: string;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export async function listCloudTiers(ctx: WorkspaceContext, q: TierQuery): Promise<unknown[]> {
|
|
203
|
+
const params: Record<string, string> = workspaceAuthQuery(ctx);
|
|
204
|
+
if (q.provider) params.provider = q.provider;
|
|
205
|
+
if (q.resource_type) params.resource_type = q.resource_type;
|
|
206
|
+
if (q.db_type) params.db_type = q.db_type;
|
|
207
|
+
const result = await client(ctx).getPath<unknown>('/integrations/v1/cloud/tiers', params);
|
|
208
|
+
return unwrapList<unknown>(result);
|
|
209
|
+
}
|