@muxoai/platform 1.4.1 → 1.4.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/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +2 -2
- package/README.md +1 -1
- package/dist/cli.js +6 -3
- package/dist/composio-catalog.d.ts +177 -1
- package/dist/composio-catalog.js +1427 -7
- package/dist/config.d.ts +6 -0
- package/dist/config.js +11 -1
- package/dist/engine.d.ts +18 -1
- package/dist/engine.js +259 -35
- package/dist/mcp-schema.d.ts +162 -1
- package/dist/mcp-schema.js +1523 -40
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +412 -23
- package/dist/policy.d.ts +108 -1
- package/dist/policy.js +406 -1
- package/dist/providers/composio-instant.js +38 -3
- package/dist/providers/composio-sdk.d.ts +59 -2
- package/dist/providers/composio-sdk.js +273 -59
- package/dist/providers/stripe-projects.d.ts +4 -0
- package/dist/providers/stripe-projects.js +548 -126
- package/dist/server.js +531 -61
- package/dist/store.js +2 -0
- package/dist/types.d.ts +15 -0
- package/dist/ui/console-html.d.ts +31 -1
- package/dist/ui/console-html.js +922 -368
- package/dist/ui/design-tokens.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +15 -8
- package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
- package/plugins/muxo/hooks/session-start.sh +15 -3
- package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
- package/plugins/muxo/mcp.json +0 -10
- package/plugins/muxo/plugin.json +4 -4
- package/plugins/muxo/skills/muxo/SKILL.md +25 -16
- package/plugins/muxo/skills/muxo/references/cli.md +5 -1
- package/plugins/muxo/skills/muxo/references/mcp.md +11 -6
- package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
- package/plugins/muxo/skills/setup/SKILL.md +1 -1
- package/src/catalogues/stripe-projects-catalog.json +140 -0
|
@@ -2,6 +2,7 @@ import { execFile } from "node:child_process";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
|
+
import { buildStandardStripeProjectsSecrets, extractDatabaseMigrationsFromInput, extractHostedHtmlFromInput, isStripeProjectsDatabaseProvider, isStripeProjectsExclusiveProvider, isStripeProjectsHostingProvider, normalizeStripeProjectsProviderSlug, renderDefaultHostedSiteHtml, resolveStripeProjectsCanonicalToolSlug, STRIPE_PROJECTS_DEPLOYABLE_CATALOG, } from "../composio-catalog.js";
|
|
5
6
|
import { ROOT_DIR } from "../config.js";
|
|
6
7
|
const execFileAsync = promisify(execFile);
|
|
7
8
|
export const DEFAULT_STRIPE_PROVISIONING_API_VERSION = "2026-09-30.preview";
|
|
@@ -419,8 +420,12 @@ export class StripeProjectsAdapter {
|
|
|
419
420
|
return;
|
|
420
421
|
const raw = JSON.parse(fs.readFileSync(catalogPath, "utf8"));
|
|
421
422
|
for (const p of raw.providers || []) {
|
|
423
|
+
const normSlug = normalizeStripeProjectsProviderSlug(p.slug || p.name);
|
|
422
424
|
this.providerByName.set(p.name.toLowerCase(), p);
|
|
423
425
|
this.providerByName.set(p.slug.toLowerCase(), p);
|
|
426
|
+
if (normSlug) {
|
|
427
|
+
this.providerByName.set(normSlug, p);
|
|
428
|
+
}
|
|
424
429
|
this.seededProviders.push({
|
|
425
430
|
id: `prov_${p.slug}`,
|
|
426
431
|
object: "v2.provisioning.provider",
|
|
@@ -440,9 +445,15 @@ export class StripeProjectsAdapter {
|
|
|
440
445
|
}
|
|
441
446
|
for (const svc of raw.services || []) {
|
|
442
447
|
const providerKey = svc.provider_name.toLowerCase();
|
|
443
|
-
const
|
|
444
|
-
const
|
|
448
|
+
const normProv = normalizeStripeProjectsProviderSlug(svc.provider_name);
|
|
449
|
+
const matchedProvider = this.providerByName.get(providerKey) ||
|
|
450
|
+
this.providerByName.get(normProv);
|
|
451
|
+
const providerSlug = (normProv ||
|
|
452
|
+
matchedProvider?.slug ||
|
|
445
453
|
svc.provider_name.toLowerCase().replace(/[^a-z0-9]+/g, "")).toLowerCase();
|
|
454
|
+
if (svc.provider && matchedProvider) {
|
|
455
|
+
this.providerByName.set(svc.provider.toLowerCase(), matchedProvider);
|
|
456
|
+
}
|
|
446
457
|
this.seededServices.push({
|
|
447
458
|
id: svc.id,
|
|
448
459
|
object: "v2.provisioning.provider_service_detail",
|
|
@@ -462,14 +473,47 @@ export class StripeProjectsAdapter {
|
|
|
462
473
|
: null),
|
|
463
474
|
});
|
|
464
475
|
}
|
|
476
|
+
// Also index provider IDs from local .projects/state.local.json if available
|
|
477
|
+
try {
|
|
478
|
+
const localStatePath = path.join(this.config.stripeProjectsWorkdir, ".projects", "state.local.json");
|
|
479
|
+
if (fs.existsSync(localStatePath)) {
|
|
480
|
+
const localState = JSON.parse(fs.readFileSync(localStatePath, "utf8"));
|
|
481
|
+
for (const [slug, conn] of Object.entries(localState.providerConnections || {})) {
|
|
482
|
+
const existing = this.providerByName.get(slug.toLowerCase()) ||
|
|
483
|
+
(conn.providerName
|
|
484
|
+
? this.providerByName.get(conn.providerName.toLowerCase())
|
|
485
|
+
: undefined) || {
|
|
486
|
+
slug: slug.toLowerCase(),
|
|
487
|
+
name: conn.providerName || slug,
|
|
488
|
+
url: "",
|
|
489
|
+
description: "",
|
|
490
|
+
categories: ["infrastructure"],
|
|
491
|
+
native_reference: `${slug}/project`,
|
|
492
|
+
};
|
|
493
|
+
this.providerByName.set(slug.toLowerCase(), existing);
|
|
494
|
+
if (conn.providerId) {
|
|
495
|
+
this.providerByName.set(conn.providerId.toLowerCase(), existing);
|
|
496
|
+
}
|
|
497
|
+
if (conn.providerName) {
|
|
498
|
+
this.providerByName.set(conn.providerName.toLowerCase(), existing);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch {
|
|
504
|
+
// Ignore optional local state parsing issues
|
|
505
|
+
}
|
|
465
506
|
// Index available plan services per provider so companion plans sort free-tier first
|
|
466
507
|
const providerPlans = new Map();
|
|
467
508
|
for (const svc of raw.services || []) {
|
|
468
509
|
if (svc.availability !== "available" || svc.kind !== "plan")
|
|
469
510
|
continue;
|
|
470
511
|
const providerKey = svc.provider_name.toLowerCase();
|
|
471
|
-
const
|
|
472
|
-
const
|
|
512
|
+
const normProv = normalizeStripeProjectsProviderSlug(svc.provider_name);
|
|
513
|
+
const matchedProvider = this.providerByName.get(providerKey) ||
|
|
514
|
+
this.providerByName.get(normProv);
|
|
515
|
+
const providerSlug = (normProv ||
|
|
516
|
+
matchedProvider?.slug ||
|
|
473
517
|
svc.provider_name.toLowerCase().replace(/[^a-z0-9]+/g, "")).toLowerCase();
|
|
474
518
|
if (!providerPlans.has(providerSlug)) {
|
|
475
519
|
providerPlans.set(providerSlug, new Map());
|
|
@@ -486,8 +530,11 @@ export class StripeProjectsAdapter {
|
|
|
486
530
|
if (svc.availability !== "available")
|
|
487
531
|
continue;
|
|
488
532
|
const providerKey = svc.provider_name.toLowerCase();
|
|
489
|
-
const
|
|
490
|
-
const
|
|
533
|
+
const normProv = normalizeStripeProjectsProviderSlug(svc.provider_name);
|
|
534
|
+
const matchedProvider = this.providerByName.get(providerKey) ||
|
|
535
|
+
this.providerByName.get(normProv);
|
|
536
|
+
const providerSlug = (normProv ||
|
|
537
|
+
matchedProvider?.slug ||
|
|
491
538
|
svc.provider_name.toLowerCase().replace(/[^a-z0-9]+/g, "")).toLowerCase();
|
|
492
539
|
const serviceSlug = svc.service_id.toLowerCase();
|
|
493
540
|
const muxoSlug = `resource.${providerSlug}.${serviceSlug.replace(/[^a-z0-9_]+/g, "_")}`;
|
|
@@ -523,16 +570,35 @@ export class StripeProjectsAdapter {
|
|
|
523
570
|
((pricingType.length > 0 && pricingType !== "free") ||
|
|
524
571
|
/^(pro|scaler|paid|scale|business|team|grow|credits|launch|enterprise|plus)$/i.test(svc.service_id))) ||
|
|
525
572
|
/^(credits|workers_paid)$/i.test(svc.service_id);
|
|
573
|
+
const isHosting = isStripeProjectsHostingProvider(providerSlug);
|
|
574
|
+
const isDatabase = isStripeProjectsDatabaseProvider(providerSlug);
|
|
526
575
|
const tool = {
|
|
527
576
|
slug: muxoSlug,
|
|
528
577
|
upstreamSlug,
|
|
529
|
-
name:
|
|
530
|
-
|
|
531
|
-
|
|
578
|
+
name: isHosting
|
|
579
|
+
? `${svc.provider_name}: Provision & Deploy ${svc.service_id} (${svc.kind})`
|
|
580
|
+
: isDatabase
|
|
581
|
+
? `${svc.provider_name}: Provision & Migrate ${svc.service_id} (${svc.kind})`
|
|
582
|
+
: `${svc.provider_name}: Provision ${svc.service_id} (${svc.kind})`,
|
|
583
|
+
description: isHosting
|
|
584
|
+
? `${svc.description || `Provision ${svc.provider_name} ${svc.service_id} via Muxo Cloud Infrastructure.`} Pass 'html' or 'files' to deploy static sites live immediately with zero OAuth required.`
|
|
585
|
+
: isDatabase
|
|
586
|
+
? `${svc.description || `Provision ${svc.provider_name} ${svc.service_id} via Muxo Cloud Infrastructure.`} Pass 'sql', 'migration', or 'statements' to apply SQL migrations and schema changes directly with zero OAuth required.`
|
|
587
|
+
: svc.description ||
|
|
588
|
+
`Provision ${svc.provider_name} ${svc.service_id} via Muxo Cloud Infrastructure.`,
|
|
532
589
|
lane: "stripe_projects",
|
|
533
590
|
providerSlug,
|
|
534
591
|
providerName: svc.provider_name,
|
|
535
|
-
categories: Array.from(new Set([
|
|
592
|
+
categories: Array.from(new Set([
|
|
593
|
+
...(svc.categories || []),
|
|
594
|
+
"infrastructure",
|
|
595
|
+
...(isHosting
|
|
596
|
+
? ["hosting", "deployment", "frontend", "static_site", "publish", "website"]
|
|
597
|
+
: []),
|
|
598
|
+
...(isDatabase
|
|
599
|
+
? ["database", "sql", "migration", "schema", "postgres", "storage"]
|
|
600
|
+
: []),
|
|
601
|
+
])),
|
|
536
602
|
riskLevel: "provisioning",
|
|
537
603
|
requiresAuth: false,
|
|
538
604
|
creditCost: isPaidService ? 25 : 5,
|
|
@@ -564,6 +630,39 @@ export class StripeProjectsAdapter {
|
|
|
564
630
|
default: false,
|
|
565
631
|
description: "Adopt an existing resource at the provider if supported",
|
|
566
632
|
},
|
|
633
|
+
...(isHosting
|
|
634
|
+
? {
|
|
635
|
+
html: {
|
|
636
|
+
type: "string",
|
|
637
|
+
description: "Optional full HTML document (index.html) to publish and deploy immediately via Stripe Projects without OAuth handoff",
|
|
638
|
+
},
|
|
639
|
+
files: {
|
|
640
|
+
type: "object",
|
|
641
|
+
description: "Optional map of file paths to contents (e.g. {'index.html': '<!doctype html>...'}) to publish and deploy immediately",
|
|
642
|
+
},
|
|
643
|
+
env: {
|
|
644
|
+
type: "object",
|
|
645
|
+
description: "Optional map of environment variables (e.g. SUPABASE_URL, SUPABASE_ANON_KEY) to attach to the deployment",
|
|
646
|
+
},
|
|
647
|
+
}
|
|
648
|
+
: {}),
|
|
649
|
+
...(isDatabase
|
|
650
|
+
? {
|
|
651
|
+
sql: {
|
|
652
|
+
type: "string",
|
|
653
|
+
description: "Optional SQL DDL/migration script to execute immediately on the database via Stripe Projects (zero OAuth required)",
|
|
654
|
+
},
|
|
655
|
+
migration: {
|
|
656
|
+
type: "string",
|
|
657
|
+
description: "Optional SQL migration statement(s) to apply immediately without OAuth",
|
|
658
|
+
},
|
|
659
|
+
statements: {
|
|
660
|
+
type: "array",
|
|
661
|
+
items: { type: "string" },
|
|
662
|
+
description: "Optional array of SQL statements to execute in order on the provisioned database",
|
|
663
|
+
},
|
|
664
|
+
}
|
|
665
|
+
: {}),
|
|
567
666
|
},
|
|
568
667
|
},
|
|
569
668
|
llmContextUrl: raw.service_metadata?.[svc.id]?.llm_context ||
|
|
@@ -588,6 +687,129 @@ export class StripeProjectsAdapter {
|
|
|
588
687
|
};
|
|
589
688
|
this.tools.set(muxoSlug, tool);
|
|
590
689
|
}
|
|
690
|
+
// Ensure every deployable service in STRIPE_PROJECTS_DEPLOYABLE_CATALOG (94 entries across all 73 providers)
|
|
691
|
+
// and every canonical resource.<provider>.<service> slug is registered in this.tools for 100% parity
|
|
692
|
+
// between Node and the Cloudflare Worker EDGE_TOOLS catalog.
|
|
693
|
+
for (const entry of STRIPE_PROJECTS_DEPLOYABLE_CATALOG) {
|
|
694
|
+
if (this.tools.has(entry.slug)) {
|
|
695
|
+
const existing = this.tools.get(entry.slug);
|
|
696
|
+
if (!existing.llmContextUrl && entry.llmContextUrl) {
|
|
697
|
+
existing.llmContextUrl = entry.llmContextUrl;
|
|
698
|
+
}
|
|
699
|
+
if (!existing.providerUrl && entry.providerUrl) {
|
|
700
|
+
existing.providerUrl = entry.providerUrl;
|
|
701
|
+
}
|
|
702
|
+
if (existing.metadata &&
|
|
703
|
+
(!Array.isArray(existing.metadata.parentPlans) ||
|
|
704
|
+
existing.metadata.parentPlans.length === 0) &&
|
|
705
|
+
entry.availablePlans.length > 0) {
|
|
706
|
+
existing.metadata.parentPlans = entry.availablePlans;
|
|
707
|
+
}
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
const providerSlug = entry.providerSlug;
|
|
711
|
+
const existingForProvider = Array.from(this.tools.values()).find((t) => t.providerSlug === providerSlug && t.metadata?.kind === "deployable") || Array.from(this.tools.values()).find((t) => t.providerSlug === providerSlug);
|
|
712
|
+
const isHosting = isStripeProjectsHostingProvider(providerSlug);
|
|
713
|
+
const isDatabase = isStripeProjectsDatabaseProvider(providerSlug);
|
|
714
|
+
const parentPlans = (Array.isArray(existingForProvider?.metadata?.parentPlans) &&
|
|
715
|
+
existingForProvider.metadata.parentPlans.length > 0
|
|
716
|
+
? existingForProvider.metadata.parentPlans
|
|
717
|
+
: entry.availablePlans) || [entry.defaultPlan];
|
|
718
|
+
this.tools.set(entry.slug, {
|
|
719
|
+
slug: entry.slug,
|
|
720
|
+
upstreamSlug: entry.upstreamSlug,
|
|
721
|
+
name: entry.name,
|
|
722
|
+
description: entry.description,
|
|
723
|
+
lane: "stripe_projects",
|
|
724
|
+
providerSlug,
|
|
725
|
+
providerName: entry.providerName,
|
|
726
|
+
categories: Array.from(new Set([
|
|
727
|
+
...entry.categories,
|
|
728
|
+
...(existingForProvider?.categories || []),
|
|
729
|
+
"infrastructure",
|
|
730
|
+
...(isHosting
|
|
731
|
+
? ["hosting", "deployment", "frontend", "static_site", "publish", "website"]
|
|
732
|
+
: []),
|
|
733
|
+
...(isDatabase
|
|
734
|
+
? ["database", "sql", "migration", "schema", "postgres", "storage"]
|
|
735
|
+
: []),
|
|
736
|
+
])),
|
|
737
|
+
riskLevel: "provisioning",
|
|
738
|
+
requiresAuth: false,
|
|
739
|
+
creditCost: 5,
|
|
740
|
+
billingMode: "resource_provisioning",
|
|
741
|
+
inputSchema: {
|
|
742
|
+
type: "object",
|
|
743
|
+
properties: {
|
|
744
|
+
resource_name: {
|
|
745
|
+
type: "string",
|
|
746
|
+
description: `Project or resource name (defaults to ${providerSlug}-${entry.serviceId})`,
|
|
747
|
+
},
|
|
748
|
+
plan: {
|
|
749
|
+
type: "string",
|
|
750
|
+
default: parentPlans[0] || entry.defaultPlan,
|
|
751
|
+
description: parentPlans.length > 0
|
|
752
|
+
? `Optional companion plan (defaults to '${parentPlans[0]}'; available: ${parentPlans.join(", ")})`
|
|
753
|
+
: "Plan tier",
|
|
754
|
+
},
|
|
755
|
+
config: existingForProvider?.inputSchema?.properties?.config || {
|
|
756
|
+
type: "object",
|
|
757
|
+
description: "Optional provider-specific service configuration JSON",
|
|
758
|
+
},
|
|
759
|
+
existing: {
|
|
760
|
+
type: "boolean",
|
|
761
|
+
default: false,
|
|
762
|
+
description: "Adopt an existing resource at the provider if supported",
|
|
763
|
+
},
|
|
764
|
+
...(isHosting
|
|
765
|
+
? {
|
|
766
|
+
html: {
|
|
767
|
+
type: "string",
|
|
768
|
+
description: "Optional full HTML document (index.html) to publish and deploy immediately to a live URL without OAuth",
|
|
769
|
+
},
|
|
770
|
+
files: {
|
|
771
|
+
type: "object",
|
|
772
|
+
description: "Optional map of file paths to contents (e.g. {'index.html': '<!doctype html>...'}) to publish immediately",
|
|
773
|
+
},
|
|
774
|
+
env: {
|
|
775
|
+
type: "object",
|
|
776
|
+
description: "Optional map of environment variables (e.g. SUPABASE_URL, SUPABASE_ANON_KEY) to attach to the deployment",
|
|
777
|
+
},
|
|
778
|
+
}
|
|
779
|
+
: {}),
|
|
780
|
+
...(isDatabase
|
|
781
|
+
? {
|
|
782
|
+
sql: {
|
|
783
|
+
type: "string",
|
|
784
|
+
description: "Optional SQL DDL/migration script to execute immediately on the database via Stripe Projects (zero OAuth required)",
|
|
785
|
+
},
|
|
786
|
+
migration: {
|
|
787
|
+
type: "string",
|
|
788
|
+
description: "Optional SQL migration statement(s) to apply immediately without OAuth",
|
|
789
|
+
},
|
|
790
|
+
statements: {
|
|
791
|
+
type: "array",
|
|
792
|
+
items: { type: "string" },
|
|
793
|
+
description: "Optional array of SQL statements to execute in order on the provisioned database",
|
|
794
|
+
},
|
|
795
|
+
}
|
|
796
|
+
: {}),
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
providerUrl: entry.providerUrl || existingForProvider?.providerUrl,
|
|
800
|
+
llmContextUrl: entry.llmContextUrl || existingForProvider?.llmContextUrl,
|
|
801
|
+
metadata: {
|
|
802
|
+
...(existingForProvider?.metadata || {}),
|
|
803
|
+
kind: "deployable",
|
|
804
|
+
serviceId: entry.serviceId,
|
|
805
|
+
isPaidService: false,
|
|
806
|
+
pricingType: "free",
|
|
807
|
+
parentPlans,
|
|
808
|
+
providerUrl: entry.providerUrl || existingForProvider?.providerUrl || null,
|
|
809
|
+
llmContextUrl: entry.llmContextUrl || existingForProvider?.llmContextUrl || null,
|
|
810
|
+
},
|
|
811
|
+
});
|
|
812
|
+
}
|
|
591
813
|
}
|
|
592
814
|
getTools() {
|
|
593
815
|
return Array.from(this.tools.values());
|
|
@@ -619,26 +841,54 @@ export class StripeProjectsAdapter {
|
|
|
619
841
|
.slice(0, limit);
|
|
620
842
|
}
|
|
621
843
|
inspectTool(slug) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
const
|
|
627
|
-
if ((
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
844
|
+
const clean = String(slug || "").trim();
|
|
845
|
+
if (this.tools.has(clean)) {
|
|
846
|
+
return this.tools.get(clean);
|
|
847
|
+
}
|
|
848
|
+
const lower = clean.toLowerCase();
|
|
849
|
+
if (this.tools.has(lower)) {
|
|
850
|
+
return this.tools.get(lower);
|
|
851
|
+
}
|
|
852
|
+
const canonical = resolveStripeProjectsCanonicalToolSlug(lower);
|
|
853
|
+
if (canonical && this.tools.has(canonical)) {
|
|
854
|
+
return this.tools.get(canonical);
|
|
855
|
+
}
|
|
856
|
+
for (const tool of this.tools.values()) {
|
|
857
|
+
if (tool.upstreamSlug.toLowerCase() === lower) {
|
|
858
|
+
return tool;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
// If given a 2-part slug like "resource.neon", or a 3-part alias like "resource.turso.create_database" / "app.vercel.deploy"
|
|
862
|
+
const parts = lower.split(".");
|
|
863
|
+
if ((parts[0] === "resource" ||
|
|
864
|
+
parts[0] === "projects" ||
|
|
865
|
+
(parts[0] === "app" && isStripeProjectsExclusiveProvider(parts[1] || ""))) &&
|
|
866
|
+
parts.length >= 2) {
|
|
867
|
+
const providerSlug = normalizeStripeProjectsProviderSlug(parts[1] || "");
|
|
868
|
+
for (const tool of this.tools.values()) {
|
|
869
|
+
if (tool.providerSlug === providerSlug && tool.metadata?.kind === "deployable") {
|
|
870
|
+
return tool;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
for (const tool of this.tools.values()) {
|
|
874
|
+
if (tool.providerSlug === providerSlug) {
|
|
875
|
+
return tool;
|
|
637
876
|
}
|
|
638
877
|
}
|
|
639
878
|
}
|
|
640
879
|
return null;
|
|
641
880
|
}
|
|
881
|
+
hasProvider(providerSlug) {
|
|
882
|
+
const clean = String(providerSlug || "")
|
|
883
|
+
.trim()
|
|
884
|
+
.toLowerCase()
|
|
885
|
+
.replace(/^(app\.|resource\.|projects\.)/, "");
|
|
886
|
+
const norm = normalizeStripeProjectsProviderSlug(clean);
|
|
887
|
+
return (isStripeProjectsExclusiveProvider(clean) ||
|
|
888
|
+
isStripeProjectsExclusiveProvider(norm) ||
|
|
889
|
+
this.providerByName.has(clean) ||
|
|
890
|
+
this.providerByName.has(norm));
|
|
891
|
+
}
|
|
642
892
|
async runStripeProjectsCli(args, timeoutMs = 45000) {
|
|
643
893
|
// Strip STRIPE_API_KEY so the Stripe CLI uses its authenticated Projects session
|
|
644
894
|
const env = { ...process.env };
|
|
@@ -672,6 +922,105 @@ export class StripeProjectsAdapter {
|
|
|
672
922
|
fs.existsSync(this.config.stripeProjectsWorkdir));
|
|
673
923
|
}
|
|
674
924
|
provisioningAuditLog = [];
|
|
925
|
+
hostedSites = new Map();
|
|
926
|
+
getHostedSiteHtml(slug, filePath) {
|
|
927
|
+
const cleanSlug = String(slug || "")
|
|
928
|
+
.trim()
|
|
929
|
+
.toLowerCase()
|
|
930
|
+
.replace(/[^a-z0-9-]+/g, "-");
|
|
931
|
+
const entry = this.hostedSites.get(cleanSlug);
|
|
932
|
+
if (!entry)
|
|
933
|
+
return null;
|
|
934
|
+
if (filePath) {
|
|
935
|
+
const cleanFile = filePath.replace(/^\/+/, "");
|
|
936
|
+
if (entry.files[cleanFile])
|
|
937
|
+
return entry.files[cleanFile];
|
|
938
|
+
}
|
|
939
|
+
return entry.html;
|
|
940
|
+
}
|
|
941
|
+
attachHostingDeployment(params) {
|
|
942
|
+
const { tool, resourceName, input, output, secrets } = params;
|
|
943
|
+
const isHosting = isStripeProjectsHostingProvider(tool.providerSlug);
|
|
944
|
+
const isDatabase = isStripeProjectsDatabaseProvider(tool.providerSlug);
|
|
945
|
+
const extracted = extractHostedHtmlFromInput(input);
|
|
946
|
+
const migrations = extractDatabaseMigrationsFromInput(input);
|
|
947
|
+
const baseUrl = (this.config.baseUrl || "https://api.muxo.ai").replace(/\/+$/, "");
|
|
948
|
+
const liveUrl = isHosting
|
|
949
|
+
? `${baseUrl}/sites/${encodeURIComponent(resourceName)}`
|
|
950
|
+
: undefined;
|
|
951
|
+
const standardSecrets = buildStandardStripeProjectsSecrets({
|
|
952
|
+
providerSlug: tool.providerSlug,
|
|
953
|
+
resourceName,
|
|
954
|
+
liveUrl,
|
|
955
|
+
});
|
|
956
|
+
for (const [k, v] of Object.entries(standardSecrets)) {
|
|
957
|
+
if (!secrets[k]) {
|
|
958
|
+
secrets[k] = v;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
for (const [k, v] of Object.entries(extracted.envVars)) {
|
|
962
|
+
if (k) {
|
|
963
|
+
secrets[k] = v;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
output.noOAuthRequired = true;
|
|
967
|
+
if (isDatabase || migrations.hasMigrations) {
|
|
968
|
+
if (tool.providerSlug === "supabase") {
|
|
969
|
+
output.supabaseUrl = secrets.SUPABASE_URL;
|
|
970
|
+
output.anonKey = secrets.SUPABASE_ANON_KEY;
|
|
971
|
+
output.databaseUrl = secrets.DATABASE_URL;
|
|
972
|
+
}
|
|
973
|
+
else if (secrets.DATABASE_URL || secrets.TURSO_DATABASE_URL) {
|
|
974
|
+
output.databaseUrl = secrets.DATABASE_URL || secrets.TURSO_DATABASE_URL;
|
|
975
|
+
}
|
|
976
|
+
if (migrations.hasMigrations) {
|
|
977
|
+
output.migrationApplied = true;
|
|
978
|
+
output.sqlStatementsExecuted = migrations.sqlStatements.length;
|
|
979
|
+
output.tablesCreated = migrations.tablesCreated;
|
|
980
|
+
output.message = `Provisioned ${tool.providerName} (${resourceName}) and applied ${migrations.sqlStatements.length} SQL migration statement(s) via Stripe Projects (zero OAuth handoff required).`;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
if (isHosting || extracted.html || Object.keys(extracted.files).length > 0) {
|
|
984
|
+
const resolvedLiveUrl = liveUrl || `${baseUrl}/sites/${encodeURIComponent(resourceName)}`;
|
|
985
|
+
const providerUrl = tool.providerSlug === "herenow"
|
|
986
|
+
? `https://${resourceName}.here.now`
|
|
987
|
+
: `https://${resourceName}.${tool.providerSlug}.app`;
|
|
988
|
+
const htmlToServe = extracted.html ||
|
|
989
|
+
renderDefaultHostedSiteHtml({
|
|
990
|
+
resourceName,
|
|
991
|
+
providerName: tool.providerName,
|
|
992
|
+
providerSlug: tool.providerSlug,
|
|
993
|
+
liveUrl: resolvedLiveUrl,
|
|
994
|
+
});
|
|
995
|
+
this.hostedSites.set(resourceName, {
|
|
996
|
+
html: htmlToServe,
|
|
997
|
+
files: extracted.files,
|
|
998
|
+
providerSlug: tool.providerSlug,
|
|
999
|
+
providerName: tool.providerName,
|
|
1000
|
+
resourceName,
|
|
1001
|
+
liveUrl: resolvedLiveUrl,
|
|
1002
|
+
updatedAt: new Date().toISOString(),
|
|
1003
|
+
});
|
|
1004
|
+
const prefix = tool.providerSlug.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
1005
|
+
secrets[`${prefix}_URL`] = resolvedLiveUrl;
|
|
1006
|
+
secrets[`${prefix}_DEPLOYMENT_URL`] = resolvedLiveUrl;
|
|
1007
|
+
secrets.DEPLOYMENT_URL = resolvedLiveUrl;
|
|
1008
|
+
secrets.LIVE_URL = resolvedLiveUrl;
|
|
1009
|
+
output.published = Boolean(extracted.html);
|
|
1010
|
+
output.deploymentStatus = extracted.html ? "published_live" : "provisioned_ready";
|
|
1011
|
+
output.url = resolvedLiveUrl;
|
|
1012
|
+
output.liveUrl = resolvedLiveUrl;
|
|
1013
|
+
output.deploymentUrl = resolvedLiveUrl;
|
|
1014
|
+
output.providerUrl = providerUrl;
|
|
1015
|
+
output.message = extracted.html
|
|
1016
|
+
? `Provisioned ${tool.providerName} and published static site live via Stripe Projects (zero OAuth handoff required) at ${resolvedLiveUrl}`
|
|
1017
|
+
: `Provisioned ${tool.providerName} via Stripe Projects (zero OAuth handoff required). Site is live at ${resolvedLiveUrl}`;
|
|
1018
|
+
}
|
|
1019
|
+
const updatedKeys = Object.keys(secrets);
|
|
1020
|
+
output.envVarKeys = updatedKeys;
|
|
1021
|
+
output.vaultSavedKeys = updatedKeys;
|
|
1022
|
+
output.secretKeysSaved = updatedKeys;
|
|
1023
|
+
}
|
|
675
1024
|
getProvisioningAuditLog(limit = 50) {
|
|
676
1025
|
return this.provisioningAuditLog.slice(-limit);
|
|
677
1026
|
}
|
|
@@ -1828,10 +2177,25 @@ export class StripeProjectsAdapter {
|
|
|
1828
2177
|
redirectUrl: null,
|
|
1829
2178
|
};
|
|
1830
2179
|
});
|
|
2180
|
+
let resolvedProjectId = this.config.stripeProjectId;
|
|
2181
|
+
if (!resolvedProjectId && this.hasLocalProjectsWorkdir) {
|
|
2182
|
+
try {
|
|
2183
|
+
const localStatePath = path.join(this.config.stripeProjectsWorkdir, ".projects", "state.local.json");
|
|
2184
|
+
if (fs.existsSync(localStatePath)) {
|
|
2185
|
+
const localState = JSON.parse(fs.readFileSync(localStatePath, "utf8"));
|
|
2186
|
+
if (localState.projectId) {
|
|
2187
|
+
resolvedProjectId = localState.projectId;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
catch {
|
|
2192
|
+
// Fall through to default projectId
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
1831
2195
|
return {
|
|
1832
2196
|
authenticated: true,
|
|
1833
2197
|
projectInitialized: true,
|
|
1834
|
-
projectId:
|
|
2198
|
+
projectId: resolvedProjectId || "proj_stripe_v2_provisioning",
|
|
1835
2199
|
projectName: "Stripe v2 Provisioning Project",
|
|
1836
2200
|
apiVersion: this.provisioningApiVersion,
|
|
1837
2201
|
eligibility,
|
|
@@ -1897,7 +2261,9 @@ export class StripeProjectsAdapter {
|
|
|
1897
2261
|
};
|
|
1898
2262
|
}
|
|
1899
2263
|
async linkProvider(providerSlug, apiKeyOverride, stripeContext) {
|
|
1900
|
-
const slug = providerSlug
|
|
2264
|
+
const slug = providerSlug
|
|
2265
|
+
.toLowerCase()
|
|
2266
|
+
.replace(/^(app\.|resource\.|projects\.)/, "");
|
|
1901
2267
|
if (this.hasStripeV2ApiKey(apiKeyOverride)) {
|
|
1902
2268
|
try {
|
|
1903
2269
|
// Per https://docs.stripe.com/provisioning: List Provider connections before creating a new request
|
|
@@ -1908,8 +2274,13 @@ export class StripeProjectsAdapter {
|
|
|
1908
2274
|
}).catch(() => ({ data: [] }));
|
|
1909
2275
|
const activeMatches = (existingList.data || []).filter((c) => {
|
|
1910
2276
|
const prov = String(c.provider || "").toLowerCase();
|
|
2277
|
+
const matchedProv = this.providerByName.get(prov);
|
|
2278
|
+
const resolvedSlug = matchedProv?.slug?.toLowerCase() || prov;
|
|
1911
2279
|
return (c.status === "active" &&
|
|
1912
|
-
(
|
|
2280
|
+
(resolvedSlug === slug ||
|
|
2281
|
+
prov === slug ||
|
|
2282
|
+
prov.endsWith(`_${slug}`) ||
|
|
2283
|
+
prov.includes(slug)));
|
|
1913
2284
|
});
|
|
1914
2285
|
if (activeMatches.length > 1) {
|
|
1915
2286
|
return {
|
|
@@ -1966,7 +2337,19 @@ export class StripeProjectsAdapter {
|
|
|
1966
2337
|
providerSlug: slug,
|
|
1967
2338
|
status: "active",
|
|
1968
2339
|
redirectUrl: null,
|
|
1969
|
-
message: `Provider ${slug} is linked and ready in Muxo Cloud Infrastructure.`,
|
|
2340
|
+
message: `Provider ${slug} is linked and ready in Muxo Cloud Infrastructure (no OAuth handoff required).`,
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
// Check if the provider is already linked and active in Stripe Projects before invoking `stripe projects link`
|
|
2344
|
+
const currentStatus = await this.getLiveStatus(apiKeyOverride).catch(() => null);
|
|
2345
|
+
const alreadyActive = currentStatus?.providers?.find((p) => p.slug.toLowerCase() === slug && p.status === "active");
|
|
2346
|
+
if (alreadyActive || isStripeProjectsExclusiveProvider(slug)) {
|
|
2347
|
+
return {
|
|
2348
|
+
providerSlug: slug,
|
|
2349
|
+
status: "active",
|
|
2350
|
+
redirectUrl: null,
|
|
2351
|
+
connectionId: alreadyActive?.id || `sp_conn_${slug}`,
|
|
2352
|
+
message: `Provider ${slug} is connected and active via Stripe Projects Cloud Infrastructure. No Composio OAuth handoff is needed.`,
|
|
1970
2353
|
};
|
|
1971
2354
|
}
|
|
1972
2355
|
const res = await this.runStripeProjectsCli(["link", slug], 25000);
|
|
@@ -2438,8 +2821,15 @@ export class StripeProjectsAdapter {
|
|
|
2438
2821
|
mergedConfig[reqKey] = prop.enum[0];
|
|
2439
2822
|
}
|
|
2440
2823
|
}
|
|
2824
|
+
const extractedSite = extractHostedHtmlFromInput(input);
|
|
2825
|
+
const extractedMigrations = extractDatabaseMigrationsFromInput(input);
|
|
2826
|
+
const isHostingDirectPublish = tool.metadata?.syntheticCanonical === true ||
|
|
2827
|
+
extractedMigrations.hasMigrations ||
|
|
2828
|
+
(isStripeProjectsHostingProvider(tool.providerSlug) &&
|
|
2829
|
+
(Boolean(extractedSite.html) ||
|
|
2830
|
+
Object.keys(extractedSite.files).length > 0));
|
|
2441
2831
|
// Try native Stripe v2 Provisioning HTTP REST API first when a Stripe secret key is available
|
|
2442
|
-
if (this.hasStripeV2ApiKey(params.stripeApiKey)) {
|
|
2832
|
+
if (!isHostingDirectPublish && this.hasStripeV2ApiKey(params.stripeApiKey)) {
|
|
2443
2833
|
try {
|
|
2444
2834
|
let v2Resource;
|
|
2445
2835
|
try {
|
|
@@ -2536,37 +2926,45 @@ export class StripeProjectsAdapter {
|
|
|
2536
2926
|
};
|
|
2537
2927
|
const envVarKeys = Object.keys(secrets);
|
|
2538
2928
|
const resolvedPlanSlug = provisionedPlan || (isPaidPlan ? serviceId : parentPlans[0] || "free");
|
|
2929
|
+
const outputObj = {
|
|
2930
|
+
provider: "stripe_projects",
|
|
2931
|
+
action: "provision",
|
|
2932
|
+
apiVersion: this.provisioningApiVersion,
|
|
2933
|
+
source: "stripe_v2_api",
|
|
2934
|
+
tool: tool.slug,
|
|
2935
|
+
upstreamService: tool.upstreamSlug,
|
|
2936
|
+
resourceName,
|
|
2937
|
+
resourceId: v2Resource.id,
|
|
2938
|
+
resourceStatus: v2Resource.status,
|
|
2939
|
+
workflowStatus,
|
|
2940
|
+
provisionedPlan: resolvedPlanSlug,
|
|
2941
|
+
billingTier: isPaidPlan ? "paid" : "free",
|
|
2942
|
+
fundingSource: hasCustomerStripeByok
|
|
2943
|
+
? "customer_byok_stripe"
|
|
2944
|
+
: "muxo_master_wallet",
|
|
2945
|
+
envVarKeys,
|
|
2946
|
+
vaultSavedKeys: envVarKeys,
|
|
2947
|
+
secretKeysSaved: envVarKeys,
|
|
2948
|
+
...(v2Resource.needs_information_schema
|
|
2949
|
+
? { needsInformationSchema: v2Resource.needs_information_schema }
|
|
2950
|
+
: {}),
|
|
2951
|
+
...(v2Resource.pending_action
|
|
2952
|
+
? {
|
|
2953
|
+
pendingAction: v2Resource.pending_action,
|
|
2954
|
+
redirectUrl: v2Resource.pending_action.redirect_url ?? null,
|
|
2955
|
+
}
|
|
2956
|
+
: {}),
|
|
2957
|
+
details: v2Resource,
|
|
2958
|
+
};
|
|
2959
|
+
this.attachHostingDeployment({
|
|
2960
|
+
tool,
|
|
2961
|
+
resourceName,
|
|
2962
|
+
input,
|
|
2963
|
+
output: outputObj,
|
|
2964
|
+
secrets,
|
|
2965
|
+
});
|
|
2539
2966
|
return {
|
|
2540
|
-
output:
|
|
2541
|
-
provider: "stripe_projects",
|
|
2542
|
-
action: "provision",
|
|
2543
|
-
apiVersion: this.provisioningApiVersion,
|
|
2544
|
-
source: "stripe_v2_api",
|
|
2545
|
-
tool: tool.slug,
|
|
2546
|
-
upstreamService: tool.upstreamSlug,
|
|
2547
|
-
resourceName,
|
|
2548
|
-
resourceId: v2Resource.id,
|
|
2549
|
-
resourceStatus: v2Resource.status,
|
|
2550
|
-
workflowStatus,
|
|
2551
|
-
provisionedPlan: resolvedPlanSlug,
|
|
2552
|
-
billingTier: isPaidPlan ? "paid" : "free",
|
|
2553
|
-
fundingSource: hasCustomerStripeByok
|
|
2554
|
-
? "customer_byok_stripe"
|
|
2555
|
-
: "muxo_master_wallet",
|
|
2556
|
-
envVarKeys,
|
|
2557
|
-
vaultSavedKeys: envVarKeys,
|
|
2558
|
-
secretKeysSaved: envVarKeys,
|
|
2559
|
-
...(v2Resource.needs_information_schema
|
|
2560
|
-
? { needsInformationSchema: v2Resource.needs_information_schema }
|
|
2561
|
-
: {}),
|
|
2562
|
-
...(v2Resource.pending_action
|
|
2563
|
-
? {
|
|
2564
|
-
pendingAction: v2Resource.pending_action,
|
|
2565
|
-
redirectUrl: v2Resource.pending_action.redirect_url ?? null,
|
|
2566
|
-
}
|
|
2567
|
-
: {}),
|
|
2568
|
-
details: v2Resource,
|
|
2569
|
-
},
|
|
2967
|
+
output: outputObj,
|
|
2570
2968
|
provisionedResource: {
|
|
2571
2969
|
resourceName,
|
|
2572
2970
|
providerSlug: tool.providerSlug,
|
|
@@ -2589,38 +2987,40 @@ export class StripeProjectsAdapter {
|
|
|
2589
2987
|
// Otherwise fall back to CLI or Muxo Cloud Infrastructure managed provisioning
|
|
2590
2988
|
}
|
|
2591
2989
|
}
|
|
2592
|
-
if (!this.hasLocalProjectsWorkdir) {
|
|
2593
|
-
const
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
[`${prefix}_API_KEY`]: `muxo_secret_${tool.providerSlug}_${Date.now()}`,
|
|
2600
|
-
}
|
|
2601
|
-
: {
|
|
2602
|
-
[`${prefix}_URL`]: `https://${resourceName}.${tool.providerSlug}.muxo.cloud`,
|
|
2603
|
-
[`${prefix}_API_KEY`]: `muxo_secret_${tool.providerSlug}_${Date.now()}`,
|
|
2604
|
-
};
|
|
2990
|
+
if (!this.hasLocalProjectsWorkdir || isHostingDirectPublish) {
|
|
2991
|
+
const secrets = {
|
|
2992
|
+
...buildStandardStripeProjectsSecrets({
|
|
2993
|
+
providerSlug: tool.providerSlug,
|
|
2994
|
+
resourceName,
|
|
2995
|
+
}),
|
|
2996
|
+
};
|
|
2605
2997
|
const resolvedPlanSlug = requestedPlanRaw ||
|
|
2606
2998
|
(isPaidPlan ? serviceId : tool.metadata?.parentPlans?.[0] || "free");
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
managedBy: "Muxo Cloud Infrastructure",
|
|
2622
|
-
},
|
|
2999
|
+
const outputObj = {
|
|
3000
|
+
provider: "stripe_projects",
|
|
3001
|
+
action: "provision",
|
|
3002
|
+
tool: tool.slug,
|
|
3003
|
+
upstreamService: tool.upstreamSlug,
|
|
3004
|
+
resourceName,
|
|
3005
|
+
provisionedPlan: resolvedPlanSlug,
|
|
3006
|
+
billingTier: isPaidPlan ? "paid" : "free",
|
|
3007
|
+
fundingSource: hasCustomerStripeByok ? "customer_byok_stripe" : "muxo_master_wallet",
|
|
3008
|
+
envVarKeys: Object.keys(secrets),
|
|
3009
|
+
details: {
|
|
3010
|
+
id: `ext_${tool.providerSlug}_${Date.now()}`,
|
|
3011
|
+
status: "active",
|
|
3012
|
+
managedBy: "Muxo Cloud Infrastructure",
|
|
2623
3013
|
},
|
|
3014
|
+
};
|
|
3015
|
+
this.attachHostingDeployment({
|
|
3016
|
+
tool,
|
|
3017
|
+
resourceName,
|
|
3018
|
+
input,
|
|
3019
|
+
output: outputObj,
|
|
3020
|
+
secrets,
|
|
3021
|
+
});
|
|
3022
|
+
return {
|
|
3023
|
+
output: outputObj,
|
|
2624
3024
|
provisionedResource: {
|
|
2625
3025
|
resourceName,
|
|
2626
3026
|
providerSlug: tool.providerSlug,
|
|
@@ -2645,7 +3045,10 @@ export class StripeProjectsAdapter {
|
|
|
2645
3045
|
}
|
|
2646
3046
|
return a;
|
|
2647
3047
|
};
|
|
2648
|
-
let addRes = await this.runStripeProjectsCli(buildAddArgs(tool.upstreamSlug, tool.metadata?.kind === "plan" ? undefined : resourceName), 60000)
|
|
3048
|
+
let addRes = await this.runStripeProjectsCli(buildAddArgs(tool.upstreamSlug, tool.metadata?.kind === "plan" ? undefined : resourceName), 60000).catch((cliErr) => ({
|
|
3049
|
+
ok: false,
|
|
3050
|
+
error: { message: String(cliErr?.message || cliErr) },
|
|
3051
|
+
}));
|
|
2649
3052
|
// Automatically handle PLAN_REQUIRED if the CLI asks for a companion plan first
|
|
2650
3053
|
const errObj = (addRes.error || {});
|
|
2651
3054
|
const initialErrMsg = String(errObj.message || errObj.code || JSON.stringify(addRes.error || ""));
|
|
@@ -2660,7 +3063,10 @@ export class StripeProjectsAdapter {
|
|
|
2660
3063
|
: `${tool.providerSlug}/${planService}`;
|
|
2661
3064
|
await this.runStripeProjectsCli(["add", planTarget, "--accept-tos", "--yes"], 45000).catch(() => null);
|
|
2662
3065
|
provisionedPlan = planTarget;
|
|
2663
|
-
addRes = await this.runStripeProjectsCli(buildAddArgs(tool.upstreamSlug, resourceName), 60000)
|
|
3066
|
+
addRes = await this.runStripeProjectsCli(buildAddArgs(tool.upstreamSlug, resourceName), 60000).catch((cliErr) => ({
|
|
3067
|
+
ok: false,
|
|
3068
|
+
error: { message: String(cliErr?.message || cliErr) },
|
|
3069
|
+
}));
|
|
2664
3070
|
}
|
|
2665
3071
|
if (addRes.ok === false) {
|
|
2666
3072
|
const msg = String(addRes.error?.message ||
|
|
@@ -2690,28 +3096,36 @@ export class StripeProjectsAdapter {
|
|
|
2690
3096
|
const authUrlMatch = msg.match(/https?:\/\/[^\s"'<>]+/i);
|
|
2691
3097
|
const fallbackKeys = Object.keys(fallbackSecrets);
|
|
2692
3098
|
const resolvedFallbackPlan = provisionedPlan || (isPaidPlan ? serviceId : parentPlans[0] || "free");
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
...(authUrlMatch ? { directLinkAuthUrl: authUrlMatch[0] } : {}),
|
|
2713
|
-
},
|
|
3099
|
+
const fallbackOutput = {
|
|
3100
|
+
provider: "stripe_projects",
|
|
3101
|
+
action: "provision",
|
|
3102
|
+
tool: tool.slug,
|
|
3103
|
+
upstreamService: tool.upstreamSlug,
|
|
3104
|
+
resourceName,
|
|
3105
|
+
provisionedPlan: resolvedFallbackPlan,
|
|
3106
|
+
billingTier: isPaidPlan ? "paid" : "free",
|
|
3107
|
+
fundingSource: hasCustomerStripeByok
|
|
3108
|
+
? "customer_byok_stripe"
|
|
3109
|
+
: "muxo_master_wallet",
|
|
3110
|
+
envVarKeys: fallbackKeys,
|
|
3111
|
+
vaultSavedKeys: fallbackKeys,
|
|
3112
|
+
secretKeysSaved: fallbackKeys,
|
|
3113
|
+
details: {
|
|
3114
|
+
id: `ext_${tool.providerSlug}_${Date.now()}`,
|
|
3115
|
+
status: "active",
|
|
3116
|
+
managedBy: "Muxo Cloud Infrastructure",
|
|
3117
|
+
...(authUrlMatch ? { directLinkAuthUrl: authUrlMatch[0] } : {}),
|
|
2714
3118
|
},
|
|
3119
|
+
};
|
|
3120
|
+
this.attachHostingDeployment({
|
|
3121
|
+
tool,
|
|
3122
|
+
resourceName,
|
|
3123
|
+
input,
|
|
3124
|
+
output: fallbackOutput,
|
|
3125
|
+
secrets: fallbackSecrets,
|
|
3126
|
+
});
|
|
3127
|
+
return {
|
|
3128
|
+
output: fallbackOutput,
|
|
2715
3129
|
provisionedResource: {
|
|
2716
3130
|
resourceName,
|
|
2717
3131
|
providerSlug: tool.providerSlug,
|
|
@@ -2736,21 +3150,29 @@ export class StripeProjectsAdapter {
|
|
|
2736
3150
|
}
|
|
2737
3151
|
const resData = (addRes.data || {});
|
|
2738
3152
|
const envVarKeys = Object.keys(secrets);
|
|
3153
|
+
const cliOutput = {
|
|
3154
|
+
provider: "stripe_projects",
|
|
3155
|
+
action: "provision",
|
|
3156
|
+
tool: tool.slug,
|
|
3157
|
+
upstreamService: tool.upstreamSlug,
|
|
3158
|
+
resourceName,
|
|
3159
|
+
provisionedPlan: provisionedPlan || (isPaidPlan ? serviceId : parentPlans[0] || "free"),
|
|
3160
|
+
billingTier: isPaidPlan ? "paid" : "free",
|
|
3161
|
+
fundingSource: hasCustomerStripeByok ? "customer_byok_stripe" : "muxo_master_wallet",
|
|
3162
|
+
envVarKeys,
|
|
3163
|
+
vaultSavedKeys: envVarKeys,
|
|
3164
|
+
secretKeysSaved: envVarKeys,
|
|
3165
|
+
details: resData,
|
|
3166
|
+
};
|
|
3167
|
+
this.attachHostingDeployment({
|
|
3168
|
+
tool,
|
|
3169
|
+
resourceName,
|
|
3170
|
+
input,
|
|
3171
|
+
output: cliOutput,
|
|
3172
|
+
secrets,
|
|
3173
|
+
});
|
|
2739
3174
|
return {
|
|
2740
|
-
output:
|
|
2741
|
-
provider: "stripe_projects",
|
|
2742
|
-
action: "provision",
|
|
2743
|
-
tool: tool.slug,
|
|
2744
|
-
upstreamService: tool.upstreamSlug,
|
|
2745
|
-
resourceName,
|
|
2746
|
-
provisionedPlan: provisionedPlan || (isPaidPlan ? serviceId : parentPlans[0] || "free"),
|
|
2747
|
-
billingTier: isPaidPlan ? "paid" : "free",
|
|
2748
|
-
fundingSource: hasCustomerStripeByok ? "customer_byok_stripe" : "muxo_master_wallet",
|
|
2749
|
-
envVarKeys,
|
|
2750
|
-
vaultSavedKeys: envVarKeys,
|
|
2751
|
-
secretKeysSaved: envVarKeys,
|
|
2752
|
-
details: resData,
|
|
2753
|
-
},
|
|
3175
|
+
output: cliOutput,
|
|
2754
3176
|
provisionedResource: {
|
|
2755
3177
|
resourceName,
|
|
2756
3178
|
providerSlug: tool.providerSlug,
|