@optima-chat/dev-skills 0.7.33 → 0.7.36

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 (40) hide show
  1. package/AGENTS.md +3 -0
  2. package/bin/helpers/billing-http.ts +191 -0
  3. package/bin/helpers/confirm-prompt.ts +23 -0
  4. package/bin/helpers/entitlement/grant.ts +70 -0
  5. package/bin/helpers/entitlement/list.ts +77 -0
  6. package/bin/helpers/entitlement/revoke.ts +116 -0
  7. package/bin/helpers/entitlement.ts +32 -0
  8. package/bin/helpers/infisical-secrets.ts +41 -0
  9. package/bin/helpers/plugin/set-default.ts +65 -0
  10. package/bin/helpers/plugin/set-paid.ts +69 -0
  11. package/bin/helpers/plugin/show.ts +42 -0
  12. package/bin/helpers/plugin.ts +32 -0
  13. package/bin/helpers/product/add-channel.ts +78 -0
  14. package/bin/helpers/product/create.ts +96 -0
  15. package/bin/helpers/product/show.ts +43 -0
  16. package/bin/helpers/product/toggle-channel.ts +56 -0
  17. package/bin/helpers/product/update.ts +72 -0
  18. package/bin/helpers/product.ts +46 -0
  19. package/dist/bin/helpers/billing-http.js +153 -0
  20. package/dist/bin/helpers/confirm-prompt.js +54 -0
  21. package/dist/bin/helpers/entitlement/grant.js +73 -0
  22. package/dist/bin/helpers/entitlement/list.js +62 -0
  23. package/dist/bin/helpers/entitlement/revoke.js +105 -0
  24. package/dist/bin/helpers/entitlement.js +39 -0
  25. package/dist/bin/helpers/infisical-secrets.js +33 -0
  26. package/dist/bin/helpers/plugin/set-default.js +61 -0
  27. package/dist/bin/helpers/plugin/set-paid.js +65 -0
  28. package/dist/bin/helpers/plugin/show.js +45 -0
  29. package/dist/bin/helpers/plugin.js +39 -0
  30. package/dist/bin/helpers/product/add-channel.js +95 -0
  31. package/dist/bin/helpers/product/create.js +124 -0
  32. package/dist/bin/helpers/product/show.js +46 -0
  33. package/dist/bin/helpers/product/toggle-channel.js +61 -0
  34. package/dist/bin/helpers/product/update.js +92 -0
  35. package/dist/bin/helpers/product.js +53 -0
  36. package/docs/superpowers/plans/2026-05-24-marketplace-admin-cli-impl.md +1973 -0
  37. package/docs/superpowers/plans/2026-05-25-optima-plugin-cli-impl.md +700 -0
  38. package/docs/superpowers/specs/2026-05-24-marketplace-admin-cli-design.md +324 -0
  39. package/docs/superpowers/specs/2026-05-25-optima-plugin-cli-design.md +156 -0
  40. package/package.json +8 -5
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runShow = runShow;
4
+ const billing_http_1 = require("../billing-http");
5
+ function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
7
+ console.log(`Usage: optima-plugin show --slug <slug> [options]
8
+
9
+ Required:
10
+ --slug <slug>
11
+
12
+ Optional:
13
+ --env stage|prod (default: stage)
14
+
15
+ Note: reads the public GET /api/plugins/:slug — shows isPaid, salesUrl, and
16
+ descriptive fields, but NOT defaultForUser / status / trustLevel (public
17
+ endpoint omits them). Returns 404 for non-ACTIVE plugins.`);
18
+ process.exit(0);
19
+ }
20
+ const out = { env: 'stage' };
21
+ for (let i = 0; i < argv.length; i++) {
22
+ const a = argv[i];
23
+ const next = argv[i + 1];
24
+ switch (a) {
25
+ case '--slug':
26
+ out.slug = next;
27
+ i++;
28
+ break;
29
+ case '--env':
30
+ out.env = next;
31
+ i++;
32
+ break;
33
+ default: throw new Error(`Unknown arg: ${a}`);
34
+ }
35
+ }
36
+ if (!out.slug)
37
+ throw new Error('--slug required');
38
+ return out;
39
+ }
40
+ async function runShow(argv) {
41
+ const args = parseArgs(argv);
42
+ (0, billing_http_1.validateEnv)(args.env);
43
+ const res = await (0, billing_http_1.callSkills)(args.env, 'GET', `/api/plugins/${encodeURIComponent(args.slug)}`);
44
+ console.log(JSON.stringify(res.body, null, 2));
45
+ }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const show_1 = require("./plugin/show");
5
+ const set_paid_1 = require("./plugin/set-paid");
6
+ const set_default_1 = require("./plugin/set-default");
7
+ function printHelp() {
8
+ console.log(`Usage: optima-plugin <subcommand> [options]
9
+
10
+ Subcommands:
11
+ show Show a plugin's marketplace state (isPaid, salesUrl, ... ACTIVE plugins only)
12
+ set-paid Flip a plugin's isPaid flag (the user-facing paid/free gate)
13
+ set-default Flip a plugin's defaultForUser flag
14
+
15
+ Run 'optima-plugin <subcommand> --help' for subcommand-specific options.`);
16
+ }
17
+ async function main() {
18
+ const [, , subcommand, ...rest] = process.argv;
19
+ if (!subcommand || subcommand === '-h' || subcommand === '--help') {
20
+ printHelp();
21
+ process.exit(0);
22
+ }
23
+ switch (subcommand) {
24
+ case 'show':
25
+ await (0, show_1.runShow)(rest);
26
+ break;
27
+ case 'set-paid':
28
+ await (0, set_paid_1.runSetPaid)(rest);
29
+ break;
30
+ case 'set-default':
31
+ await (0, set_default_1.runSetDefault)(rest);
32
+ break;
33
+ default:
34
+ console.error(`Unknown subcommand: ${subcommand}`);
35
+ printHelp();
36
+ process.exit(1);
37
+ }
38
+ }
39
+ main().catch((err) => { console.error(err.message); process.exit(1); });
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAddChannel = runAddChannel;
4
+ const billing_http_1 = require("../billing-http");
5
+ function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
7
+ console.log(`Usage: optima-product add-channel --key <productKey> --provider STRIPE --stripe-price-id <price_xxx> --price-cents N --currency USD [options]
8
+
9
+ Required:
10
+ --key <productKey>
11
+ --provider STRIPE v1 CLI accepts only STRIPE (schema supports more)
12
+ --stripe-price-id <price_xxx> Pre-created in Stripe Dashboard; wire-mapped to externalProductId
13
+ --price-cents N MUST be > 0; should match Stripe Price's unit_amount (NOT verified)
14
+ --currency USD Should match Stripe Price's currency (NOT verified)
15
+
16
+ Optional:
17
+ --enabled true|false default: true
18
+ --metadata '<json>'
19
+ --env stage|prod (default: stage)`);
20
+ process.exit(0);
21
+ }
22
+ const out = { env: 'stage' };
23
+ for (let i = 0; i < argv.length; i++) {
24
+ const a = argv[i];
25
+ const next = argv[i + 1];
26
+ switch (a) {
27
+ case '--key':
28
+ out.key = next;
29
+ i++;
30
+ break;
31
+ case '--provider':
32
+ out.provider = next;
33
+ i++;
34
+ break;
35
+ case '--stripe-price-id':
36
+ out.stripePriceId = next;
37
+ i++;
38
+ break;
39
+ case '--price-cents':
40
+ out.priceCents = parseInt(next, 10);
41
+ i++;
42
+ break;
43
+ case '--currency':
44
+ out.currency = next;
45
+ i++;
46
+ break;
47
+ case '--enabled':
48
+ out.enabled = next === 'true';
49
+ i++;
50
+ break;
51
+ case '--metadata':
52
+ out.metadata = JSON.parse(next);
53
+ i++;
54
+ break;
55
+ case '--env':
56
+ out.env = next;
57
+ i++;
58
+ break;
59
+ default: throw new Error(`Unknown arg: ${a}`);
60
+ }
61
+ }
62
+ if (!out.key)
63
+ throw new Error('--key required');
64
+ if (!out.provider)
65
+ throw new Error('--provider required');
66
+ if (out.provider !== 'STRIPE')
67
+ throw new Error(`v1 CLI accepts only --provider STRIPE (got ${out.provider})`);
68
+ if (!out.stripePriceId)
69
+ throw new Error('--stripe-price-id required');
70
+ if (out.priceCents === undefined || !Number.isFinite(out.priceCents))
71
+ throw new Error('--price-cents required (integer)');
72
+ if (out.priceCents <= 0)
73
+ throw new Error('--price-cents must be > 0');
74
+ if (!out.currency)
75
+ throw new Error('--currency required');
76
+ return out;
77
+ }
78
+ async function runAddChannel(argv) {
79
+ const args = parseArgs(argv);
80
+ (0, billing_http_1.validateEnv)(args.env);
81
+ const body = {
82
+ provider: args.provider,
83
+ externalProductId: args.stripePriceId,
84
+ priceCents: args.priceCents,
85
+ currency: args.currency,
86
+ };
87
+ if (args.enabled !== undefined)
88
+ body.enabled = args.enabled;
89
+ if (args.metadata !== undefined)
90
+ body.metadata = args.metadata;
91
+ console.log(`\n💳 Adding ${args.provider} channel to ${args.key} on ${args.env.toUpperCase()}...`);
92
+ const res = await (0, billing_http_1.callBilling)(args.env, 'POST', `/api/billing/admin/products/${encodeURIComponent(args.key)}/channels`, body);
93
+ console.log(`✓ Created Channel (HTTP ${res.status}):`);
94
+ console.log(JSON.stringify(res.body, null, 2));
95
+ }
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runCreate = runCreate;
4
+ const billing_http_1 = require("../billing-http");
5
+ function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
7
+ console.log(`Usage: optima-product create --key <productKey> --plugins <slug1,slug2,...> --type <ProductType> [options]
8
+
9
+ Required:
10
+ --key <productKey> Unique slug
11
+ --plugins <slug1,slug2,...> Comma-separated, >=1 plugin slug
12
+ --type <ProductType> Only ONE_SHOT_SKILL accepted by v1 CLI policy
13
+
14
+ Optional:
15
+ --name "..." Convenience flag, folded into metadata.name
16
+ --description "..." Convenience flag, folded into metadata.description
17
+ --refund-window-days N
18
+ --refund-prorate-max-days N
19
+ --bundled-plan-id <planId> (joint with --bundled-duration-days)
20
+ --bundled-duration-days N
21
+ --revoke-bundled-on-refund true|false
22
+ --metadata '<json>' JSON object stored in product.metadata
23
+ --env stage|prod (default: stage)`);
24
+ process.exit(0);
25
+ }
26
+ const out = { env: 'stage', revokeBundledOnRefund: undefined };
27
+ for (let i = 0; i < argv.length; i++) {
28
+ const a = argv[i];
29
+ const next = argv[i + 1];
30
+ switch (a) {
31
+ case '--key':
32
+ out.key = next;
33
+ i++;
34
+ break;
35
+ case '--plugins':
36
+ out.plugins = next.split(',').map((s) => s.trim()).filter(Boolean);
37
+ i++;
38
+ break;
39
+ case '--type':
40
+ out.type = next;
41
+ i++;
42
+ break;
43
+ case '--name':
44
+ out.name = next;
45
+ i++;
46
+ break;
47
+ case '--description':
48
+ out.description = next;
49
+ i++;
50
+ break;
51
+ case '--refund-window-days':
52
+ out.refundWindowDays = parseInt(next, 10);
53
+ i++;
54
+ break;
55
+ case '--refund-prorate-max-days':
56
+ out.refundProrateMaxDays = parseInt(next, 10);
57
+ i++;
58
+ break;
59
+ case '--bundled-plan-id':
60
+ out.bundledPlanId = next;
61
+ i++;
62
+ break;
63
+ case '--bundled-duration-days':
64
+ out.bundledDurationDays = parseInt(next, 10);
65
+ i++;
66
+ break;
67
+ case '--revoke-bundled-on-refund':
68
+ out.revokeBundledOnRefund = next === 'true';
69
+ i++;
70
+ break;
71
+ case '--metadata':
72
+ out.metadata = JSON.parse(next);
73
+ i++;
74
+ break;
75
+ case '--env':
76
+ out.env = next;
77
+ i++;
78
+ break;
79
+ default: throw new Error(`Unknown arg: ${a}`);
80
+ }
81
+ }
82
+ if (!out.key)
83
+ throw new Error('--key required');
84
+ if (!out.plugins || out.plugins.length === 0)
85
+ throw new Error('--plugins required (>=1 slug)');
86
+ if (!out.type)
87
+ throw new Error('--type required');
88
+ if (out.type !== 'ONE_SHOT_SKILL') {
89
+ throw new Error(`v1 CLI accepts only --type ONE_SHOT_SKILL (got ${out.type}). See spec §5.1.`);
90
+ }
91
+ if ((out.bundledPlanId == null) !== (out.bundledDurationDays == null)) {
92
+ throw new Error('--bundled-plan-id and --bundled-duration-days must be set together');
93
+ }
94
+ return out;
95
+ }
96
+ async function runCreate(argv) {
97
+ const args = parseArgs(argv);
98
+ (0, billing_http_1.validateEnv)(args.env);
99
+ const body = {
100
+ productKey: args.key,
101
+ type: args.type,
102
+ pluginSlugs: args.plugins,
103
+ };
104
+ if (args.name !== undefined)
105
+ body.name = args.name;
106
+ if (args.description !== undefined)
107
+ body.description = args.description;
108
+ if (args.refundWindowDays !== undefined)
109
+ body.refundWindowDays = args.refundWindowDays;
110
+ if (args.refundProrateMaxDays !== undefined)
111
+ body.refundProrateMaxDays = args.refundProrateMaxDays;
112
+ if (args.bundledPlanId !== undefined)
113
+ body.bundledPlanId = args.bundledPlanId;
114
+ if (args.bundledDurationDays !== undefined)
115
+ body.bundledDurationDays = args.bundledDurationDays;
116
+ if (args.revokeBundledOnRefund !== undefined)
117
+ body.revokeBundledOnRefund = args.revokeBundledOnRefund;
118
+ if (args.metadata !== undefined)
119
+ body.metadata = args.metadata;
120
+ console.log(`\n🎁 Creating product ${args.key} (${args.plugins.length} plugin(s)) on ${args.env.toUpperCase()}...`);
121
+ const res = await (0, billing_http_1.callBilling)(args.env, 'POST', '/api/billing/admin/products', body);
122
+ console.log(`✓ Created Product (HTTP ${res.status}):`);
123
+ console.log(JSON.stringify(res.body, null, 2));
124
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runShow = runShow;
4
+ const billing_http_1 = require("../billing-http");
5
+ function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
7
+ console.log(`Usage: optima-product show --key <productKey> [options]
8
+
9
+ Required:
10
+ --key <productKey>
11
+
12
+ Optional:
13
+ --env stage|prod (default: stage)
14
+
15
+ Note: returns the bare Product row only — productPlugins and channels arrays
16
+ are NOT included (billing's GET /api/internal/products/:key is a plain
17
+ findUnique with no include). To inspect channels/plugins today, query the DB
18
+ directly via optima-query-db. Tracked as follow-up in spec §7.`);
19
+ process.exit(0);
20
+ }
21
+ const out = { env: 'stage' };
22
+ for (let i = 0; i < argv.length; i++) {
23
+ const a = argv[i];
24
+ const next = argv[i + 1];
25
+ switch (a) {
26
+ case '--key':
27
+ out.key = next;
28
+ i++;
29
+ break;
30
+ case '--env':
31
+ out.env = next;
32
+ i++;
33
+ break;
34
+ default: throw new Error(`Unknown arg: ${a}`);
35
+ }
36
+ }
37
+ if (!out.key)
38
+ throw new Error('--key required');
39
+ return out;
40
+ }
41
+ async function runShow(argv) {
42
+ const args = parseArgs(argv);
43
+ (0, billing_http_1.validateEnv)(args.env);
44
+ const res = await (0, billing_http_1.callBilling)(args.env, 'GET', `/api/internal/products/${encodeURIComponent(args.key)}`);
45
+ console.log(JSON.stringify(res.body, null, 2));
46
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runToggleChannel = runToggleChannel;
4
+ const billing_http_1 = require("../billing-http");
5
+ function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
7
+ console.log(`Usage: optima-product toggle-channel --key <productKey> --provider STRIPE --enabled true|false [options]
8
+
9
+ Required:
10
+ --key <productKey>
11
+ --provider STRIPE v1 CLI accepts only STRIPE
12
+ --enabled true|false
13
+
14
+ Optional:
15
+ --env stage|prod (default: stage)`);
16
+ process.exit(0);
17
+ }
18
+ const out = { env: 'stage' };
19
+ for (let i = 0; i < argv.length; i++) {
20
+ const a = argv[i];
21
+ const next = argv[i + 1];
22
+ switch (a) {
23
+ case '--key':
24
+ out.key = next;
25
+ i++;
26
+ break;
27
+ case '--provider':
28
+ out.provider = next;
29
+ i++;
30
+ break;
31
+ case '--enabled':
32
+ if (next !== 'true' && next !== 'false')
33
+ throw new Error('--enabled must be true or false');
34
+ out.enabled = next === 'true';
35
+ i++;
36
+ break;
37
+ case '--env':
38
+ out.env = next;
39
+ i++;
40
+ break;
41
+ default: throw new Error(`Unknown arg: ${a}`);
42
+ }
43
+ }
44
+ if (!out.key)
45
+ throw new Error('--key required');
46
+ if (!out.provider)
47
+ throw new Error('--provider required');
48
+ if (out.provider !== 'STRIPE')
49
+ throw new Error(`v1 CLI accepts only --provider STRIPE (got ${out.provider})`);
50
+ if (out.enabled === undefined)
51
+ throw new Error('--enabled required');
52
+ return out;
53
+ }
54
+ async function runToggleChannel(argv) {
55
+ const args = parseArgs(argv);
56
+ (0, billing_http_1.validateEnv)(args.env);
57
+ console.log(`\n🔁 Setting ${args.provider} channel enabled=${args.enabled} on ${args.key} (${args.env.toUpperCase()})...`);
58
+ const res = await (0, billing_http_1.callBilling)(args.env, 'PATCH', `/api/billing/admin/products/${encodeURIComponent(args.key)}/channels/${args.provider}`, { enabled: args.enabled });
59
+ console.log(`✓ Channel updated (HTTP ${res.status}):`);
60
+ console.log(JSON.stringify(res.body, null, 2));
61
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runUpdate = runUpdate;
4
+ const billing_http_1 = require("../billing-http");
5
+ function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
7
+ console.log(`Usage: optima-product update --key <productKey> [options]
8
+
9
+ Required:
10
+ --key <productKey>
11
+
12
+ Optional (PATCH — only included fields are updated):
13
+ --refund-window-days N | null
14
+ --refund-prorate-max-days N | null
15
+ --bundled-plan-id <planId> | null (joint with --bundled-duration-days)
16
+ --bundled-duration-days N | null
17
+ --revoke-bundled-on-refund true|false
18
+ --metadata '<json>' FULL REPLACE — Prisma does not deep-merge JSON
19
+ --env stage|prod (default: stage)
20
+
21
+ Note: productKey, type, and pluginSlugs are immutable post-create. To change plugin
22
+ membership, create a new Product with a new key.`);
23
+ process.exit(0);
24
+ }
25
+ const out = { env: 'stage' };
26
+ for (let i = 0; i < argv.length; i++) {
27
+ const a = argv[i];
28
+ const next = argv[i + 1];
29
+ const parseNullable = (v) => v === 'null' ? null : parseInt(v, 10);
30
+ switch (a) {
31
+ case '--key':
32
+ out.key = next;
33
+ i++;
34
+ break;
35
+ case '--refund-window-days':
36
+ out.refundWindowDays = parseNullable(next);
37
+ i++;
38
+ break;
39
+ case '--refund-prorate-max-days':
40
+ out.refundProrateMaxDays = parseNullable(next);
41
+ i++;
42
+ break;
43
+ case '--bundled-plan-id':
44
+ out.bundledPlanId = next === 'null' ? null : next;
45
+ i++;
46
+ break;
47
+ case '--bundled-duration-days':
48
+ out.bundledDurationDays = parseNullable(next);
49
+ i++;
50
+ break;
51
+ case '--revoke-bundled-on-refund':
52
+ out.revokeBundledOnRefund = next === 'true';
53
+ i++;
54
+ break;
55
+ case '--metadata':
56
+ out.metadata = JSON.parse(next);
57
+ i++;
58
+ break;
59
+ case '--env':
60
+ out.env = next;
61
+ i++;
62
+ break;
63
+ default: throw new Error(`Unknown arg: ${a}`);
64
+ }
65
+ }
66
+ if (!out.key)
67
+ throw new Error('--key required');
68
+ return out;
69
+ }
70
+ async function runUpdate(argv) {
71
+ const args = parseArgs(argv);
72
+ (0, billing_http_1.validateEnv)(args.env);
73
+ const body = {};
74
+ if (args.refundWindowDays !== undefined)
75
+ body.refundWindowDays = args.refundWindowDays;
76
+ if (args.refundProrateMaxDays !== undefined)
77
+ body.refundProrateMaxDays = args.refundProrateMaxDays;
78
+ if (args.bundledPlanId !== undefined)
79
+ body.bundledPlanId = args.bundledPlanId;
80
+ if (args.bundledDurationDays !== undefined)
81
+ body.bundledDurationDays = args.bundledDurationDays;
82
+ if (args.revokeBundledOnRefund !== undefined)
83
+ body.revokeBundledOnRefund = args.revokeBundledOnRefund;
84
+ if (args.metadata !== undefined)
85
+ body.metadata = args.metadata;
86
+ if (Object.keys(body).length === 0)
87
+ throw new Error('At least one updatable field must be passed');
88
+ console.log(`\n✏️ Updating product ${args.key} on ${args.env.toUpperCase()}...`);
89
+ const res = await (0, billing_http_1.callBilling)(args.env, 'PATCH', `/api/billing/admin/products/${encodeURIComponent(args.key)}`, body);
90
+ console.log(`✓ Updated Product (HTTP ${res.status}):`);
91
+ console.log(JSON.stringify(res.body, null, 2));
92
+ }
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const create_1 = require("./product/create");
5
+ const update_1 = require("./product/update");
6
+ const add_channel_1 = require("./product/add-channel");
7
+ const toggle_channel_1 = require("./product/toggle-channel");
8
+ const show_1 = require("./product/show");
9
+ const SUBCOMMANDS = ['create', 'update', 'add-channel', 'toggle-channel', 'show'];
10
+ function printHelp() {
11
+ console.log(`Usage: optima-product <subcommand> [options]
12
+
13
+ Subcommands:
14
+ create Create a Product bundling 1+ plugin slugs
15
+ update Patch refund policy / metadata on an existing Product
16
+ add-channel Attach a payment channel (Stripe Price ID) to a Product
17
+ toggle-channel Enable/disable an existing channel
18
+ show Show a Product's bare row (note: does NOT include plugins/channels)
19
+
20
+ Run 'optima-product <subcommand> --help' for subcommand-specific options.`);
21
+ }
22
+ async function main() {
23
+ const [, , subcommand, ...rest] = process.argv;
24
+ if (!subcommand || subcommand === '-h' || subcommand === '--help') {
25
+ printHelp();
26
+ process.exit(0);
27
+ }
28
+ switch (subcommand) {
29
+ case 'create':
30
+ await (0, create_1.runCreate)(rest);
31
+ break;
32
+ case 'update':
33
+ await (0, update_1.runUpdate)(rest);
34
+ break;
35
+ case 'add-channel':
36
+ await (0, add_channel_1.runAddChannel)(rest);
37
+ break;
38
+ case 'toggle-channel':
39
+ await (0, toggle_channel_1.runToggleChannel)(rest);
40
+ break;
41
+ case 'show':
42
+ await (0, show_1.runShow)(rest);
43
+ break;
44
+ default:
45
+ console.error(`Unknown subcommand: ${subcommand}`);
46
+ printHelp();
47
+ process.exit(1);
48
+ }
49
+ }
50
+ main().catch((err) => {
51
+ console.error(err.message);
52
+ process.exit(1);
53
+ });