@ductape/cli 0.2.17 → 0.2.19
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/resources.d.ts +6 -0
- package/dist/commands/resources.js +32 -0
- package/dist/index.js +9 -1
- package/dist/lib/platform-api.js +4 -4
- package/package.json +1 -1
- package/src/commands/resources.ts +30 -0
- package/src/index.ts +10 -1
- package/src/lib/platform-api.ts +4 -4
- package/test/platform-api.test.ts +23 -0
|
@@ -5,6 +5,12 @@ export declare function runEventTopicCrud(verb: string, opts: {
|
|
|
5
5
|
file?: string;
|
|
6
6
|
json?: boolean;
|
|
7
7
|
} & CommandInteractiveFlags, extraArgs: string[]): Promise<void>;
|
|
8
|
+
export declare function runNotificationMessageCrud(verb: string, opts: {
|
|
9
|
+
tag?: string;
|
|
10
|
+
notification?: string;
|
|
11
|
+
file?: string;
|
|
12
|
+
json?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
8
14
|
export declare function runResourceCrud(typeName: string, verb: string, opts: {
|
|
9
15
|
tag?: string;
|
|
10
16
|
file?: string;
|
|
@@ -61,6 +61,38 @@ export async function runEventTopicCrud(verb, opts, extraArgs) {
|
|
|
61
61
|
const result = await proxy.execute('messageBrokers', method, params);
|
|
62
62
|
printJson(result, Boolean(opts.json));
|
|
63
63
|
}
|
|
64
|
+
export async function runNotificationMessageCrud(verb, opts) {
|
|
65
|
+
const crud = verb.toLowerCase();
|
|
66
|
+
if (!['create', 'list', 'get', 'update'].includes(crud)) {
|
|
67
|
+
throw new Error('Notification message verb must be: create | list | get | update');
|
|
68
|
+
}
|
|
69
|
+
const session = requireSession();
|
|
70
|
+
const proxy = getSdkProxy(session);
|
|
71
|
+
const product = session.project.product_tag;
|
|
72
|
+
const body = ['create', 'update'].includes(crud)
|
|
73
|
+
? await resolveBody({ file: opts.file, patch: crud === 'update', requireBody: crud === 'create', interactive: false })
|
|
74
|
+
: undefined;
|
|
75
|
+
const method = `messages.${crud === 'get' ? 'fetch' : crud}`;
|
|
76
|
+
let params;
|
|
77
|
+
if (crud === 'create')
|
|
78
|
+
params = [product, body ?? {}];
|
|
79
|
+
else if (crud === 'list') {
|
|
80
|
+
if (!opts.notification)
|
|
81
|
+
throw new Error('--notification <notification-tag> is required');
|
|
82
|
+
params = [product, opts.notification];
|
|
83
|
+
}
|
|
84
|
+
else if (crud === 'get') {
|
|
85
|
+
if (!opts.tag)
|
|
86
|
+
throw new Error('--tag <notification:message> is required');
|
|
87
|
+
params = [product, opts.tag];
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
if (!opts.tag)
|
|
91
|
+
throw new Error('--tag <notification:message> is required');
|
|
92
|
+
params = [product, opts.tag, body ?? {}];
|
|
93
|
+
}
|
|
94
|
+
printJson(await proxy.execute('notifications', method, params), Boolean(opts.json));
|
|
95
|
+
}
|
|
64
96
|
export async function runResourceCrud(typeName, verb, opts, extraArgs) {
|
|
65
97
|
const crud = verb.toLowerCase();
|
|
66
98
|
if (!CRUD_VERBS.includes(crud)) {
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { runUnlink } from './commands/unlink.js';
|
|
|
12
12
|
import { runInit } from './commands/init.js';
|
|
13
13
|
import { runInstall } from './commands/install.js';
|
|
14
14
|
import { runStart, runStop, runStatus } from './commands/platform.js';
|
|
15
|
-
import { runResourceCrud, runResourcesList, runEventTopicCrud } from './commands/resources.js';
|
|
15
|
+
import { runResourceCrud, runResourcesList, runEventTopicCrud, runNotificationMessageCrud } from './commands/resources.js';
|
|
16
16
|
import { runCloud } from './commands/cloud.js';
|
|
17
17
|
import { runDb, runDbContext } from './commands/db.js';
|
|
18
18
|
import { runDbMigrate, runDbMigrateStatus, runDbMigrateRollback } from './commands/db-migrate.js';
|
|
@@ -255,6 +255,14 @@ eventTopics
|
|
|
255
255
|
.option('--json', 'JSON output')
|
|
256
256
|
.action(wrap((verb, opts) => runEventTopicCrud(verb, opts, [])));
|
|
257
257
|
const resources = program.command('resources').description('Component CRUD (sdk-proxy)');
|
|
258
|
+
const notificationMessages = program.command('notifications').description('Notification templates');
|
|
259
|
+
notificationMessages
|
|
260
|
+
.command('messages <verb>')
|
|
261
|
+
.option('-t, --tag <tag>', 'Full notification:message tag')
|
|
262
|
+
.option('-n, --notification <tag>', 'Notification tag for list')
|
|
263
|
+
.option('-f, --file <path>', 'JSON template body for create/update')
|
|
264
|
+
.option('--json', 'JSON output')
|
|
265
|
+
.action(wrap((verb, opts) => runNotificationMessageCrud(verb, opts)));
|
|
258
266
|
resources.command('types').option('--json', 'JSON output').action(wrap((opts) => runResourcesList(Boolean(opts.json))));
|
|
259
267
|
resources
|
|
260
268
|
.argument('<type>', 'Resource type (e.g. storage, database, cache …)')
|
package/dist/lib/platform-api.js
CHANGED
|
@@ -53,10 +53,10 @@ export async function getProduct(ctx, opts) {
|
|
|
53
53
|
return unwrapOne(result);
|
|
54
54
|
}
|
|
55
55
|
if (opts.tag) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
// The integrations REST fetch-by-tag route rejects current CLI login tokens with HTTP 401.
|
|
57
|
+
// Product inventory is an administrative read, so route it through the authenticated CLI
|
|
58
|
+
// SDK proxy (x-access-token), not the publishable-key runtime MCP proxy.
|
|
59
|
+
const result = await proxy(ctx).execute('product', 'fetch', [opts.tag]);
|
|
60
60
|
return unwrapOne(result);
|
|
61
61
|
}
|
|
62
62
|
throw new Error('Provide --id <product_id> or --tag <product_tag>');
|
package/package.json
CHANGED
|
@@ -73,6 +73,36 @@ export async function runEventTopicCrud(
|
|
|
73
73
|
printJson(result, Boolean(opts.json));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
export async function runNotificationMessageCrud(
|
|
77
|
+
verb: string,
|
|
78
|
+
opts: { tag?: string; notification?: string; file?: string; json?: boolean },
|
|
79
|
+
): Promise<void> {
|
|
80
|
+
const crud = verb.toLowerCase();
|
|
81
|
+
if (!['create', 'list', 'get', 'update'].includes(crud)) {
|
|
82
|
+
throw new Error('Notification message verb must be: create | list | get | update');
|
|
83
|
+
}
|
|
84
|
+
const session = requireSession();
|
|
85
|
+
const proxy = getSdkProxy(session);
|
|
86
|
+
const product = session.project.product_tag;
|
|
87
|
+
const body = ['create', 'update'].includes(crud)
|
|
88
|
+
? await resolveBody({ file: opts.file, patch: crud === 'update', requireBody: crud === 'create', interactive: false })
|
|
89
|
+
: undefined;
|
|
90
|
+
const method = `messages.${crud === 'get' ? 'fetch' : crud}`;
|
|
91
|
+
let params: unknown[];
|
|
92
|
+
if (crud === 'create') params = [product, body ?? {}];
|
|
93
|
+
else if (crud === 'list') {
|
|
94
|
+
if (!opts.notification) throw new Error('--notification <notification-tag> is required');
|
|
95
|
+
params = [product, opts.notification];
|
|
96
|
+
} else if (crud === 'get') {
|
|
97
|
+
if (!opts.tag) throw new Error('--tag <notification:message> is required');
|
|
98
|
+
params = [product, opts.tag];
|
|
99
|
+
} else {
|
|
100
|
+
if (!opts.tag) throw new Error('--tag <notification:message> is required');
|
|
101
|
+
params = [product, opts.tag, body ?? {}];
|
|
102
|
+
}
|
|
103
|
+
printJson(await proxy.execute('notifications', method, params), Boolean(opts.json));
|
|
104
|
+
}
|
|
105
|
+
|
|
76
106
|
export async function runResourceCrud(
|
|
77
107
|
typeName: string,
|
|
78
108
|
verb: string,
|
package/src/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { runUnlink } from './commands/unlink.js';
|
|
|
12
12
|
import { runInit } from './commands/init.js';
|
|
13
13
|
import { runInstall } from './commands/install.js';
|
|
14
14
|
import { runStart, runStop, runStatus } from './commands/platform.js';
|
|
15
|
-
import { runResourceCrud, runResourcesList, runEventTopicCrud } from './commands/resources.js';
|
|
15
|
+
import { runResourceCrud, runResourcesList, runEventTopicCrud, runNotificationMessageCrud } from './commands/resources.js';
|
|
16
16
|
import { runCloud } from './commands/cloud.js';
|
|
17
17
|
import { runDb, runDbContext } from './commands/db.js';
|
|
18
18
|
import { runDbMigrate, runDbMigrateStatus, runDbMigrateRollback } from './commands/db-migrate.js';
|
|
@@ -332,6 +332,15 @@ eventTopics
|
|
|
332
332
|
|
|
333
333
|
const resources = program.command('resources').description('Component CRUD (sdk-proxy)');
|
|
334
334
|
|
|
335
|
+
const notificationMessages = program.command('notifications').description('Notification templates');
|
|
336
|
+
notificationMessages
|
|
337
|
+
.command('messages <verb>')
|
|
338
|
+
.option('-t, --tag <tag>', 'Full notification:message tag')
|
|
339
|
+
.option('-n, --notification <tag>', 'Notification tag for list')
|
|
340
|
+
.option('-f, --file <path>', 'JSON template body for create/update')
|
|
341
|
+
.option('--json', 'JSON output')
|
|
342
|
+
.action(wrap((verb: string, opts) => runNotificationMessageCrud(verb, opts)));
|
|
343
|
+
|
|
335
344
|
resources.command('types').option('--json', 'JSON output').action(wrap((opts) => runResourcesList(Boolean(opts.json))));
|
|
336
345
|
|
|
337
346
|
resources
|
package/src/lib/platform-api.ts
CHANGED
|
@@ -69,10 +69,10 @@ export async function getProduct(
|
|
|
69
69
|
return unwrapOne(result);
|
|
70
70
|
}
|
|
71
71
|
if (opts.tag) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
// The integrations REST fetch-by-tag route rejects current CLI login tokens with HTTP 401.
|
|
73
|
+
// Product inventory is an administrative read, so route it through the authenticated CLI
|
|
74
|
+
// SDK proxy (x-access-token), not the publishable-key runtime MCP proxy.
|
|
75
|
+
const result = await proxy(ctx).execute<unknown>('product', 'fetch', [opts.tag]);
|
|
76
76
|
return unwrapOne(result);
|
|
77
77
|
}
|
|
78
78
|
throw new Error('Provide --id <product_id> or --tag <product_tag>');
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
3
5
|
|
|
4
6
|
// Test unwrap helpers indirectly via exported patterns — use small inline copies for unit scope
|
|
5
7
|
function unwrapList<T>(result: unknown): T[] {
|
|
@@ -16,4 +18,25 @@ describe('platform-api helpers', () => {
|
|
|
16
18
|
assert.deepEqual(unwrapList({ data: [{ tag: 'b' }] }), [{ tag: 'b' }]);
|
|
17
19
|
assert.deepEqual(unwrapList({}), []);
|
|
18
20
|
});
|
|
21
|
+
|
|
22
|
+
it('routes product fetch-by-tag through the authenticated CLI SDK proxy', () => {
|
|
23
|
+
const source = readFileSync(
|
|
24
|
+
fileURLToPath(new URL('../src/lib/platform-api.ts', import.meta.url)),
|
|
25
|
+
'utf8',
|
|
26
|
+
);
|
|
27
|
+
assert.match(source, /proxy\(ctx\)\.execute<unknown>\('product', 'fetch', \[opts\.tag\]\)/);
|
|
28
|
+
assert.doesNotMatch(
|
|
29
|
+
source,
|
|
30
|
+
/getPath<unknown>\(`\/integrations\/v1\/fetch\/tag`/,
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('exposes notification message administration', () => {
|
|
35
|
+
const source = readFileSync(
|
|
36
|
+
fileURLToPath(new URL('../src/commands/resources.ts', import.meta.url)),
|
|
37
|
+
'utf8',
|
|
38
|
+
);
|
|
39
|
+
assert.match(source, /runNotificationMessageCrud/);
|
|
40
|
+
assert.match(source, /`messages\.\$\{crud === 'get' \? 'fetch' : crud\}`/);
|
|
41
|
+
});
|
|
19
42
|
});
|