kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/715/head
rodzic
a014881c89
commit
b71ce684c0
|
@ -173,12 +173,13 @@ export const consumerSelectSchema = createSelectSchema(consumers, {
|
|||
.any()
|
||||
.refine(
|
||||
(deployment): boolean =>
|
||||
deploymentSelectSchema.safeParse(deployment).success,
|
||||
!deployment || deploymentSelectSchema.safeParse(deployment).success,
|
||||
{
|
||||
message: 'Invalid lastDeployment'
|
||||
}
|
||||
)
|
||||
.transform((deployment): any => {
|
||||
if (!deployment) return undefined
|
||||
return deploymentSelectSchema.parse(deployment)
|
||||
})
|
||||
.optional()
|
||||
|
|
|
@ -195,12 +195,14 @@ export const deploymentSelectSchema = createSelectSchema(deployments, {
|
|||
project: z
|
||||
.any()
|
||||
.refine(
|
||||
(project): boolean => projectSelectSchema.safeParse(project).success,
|
||||
(project): boolean =>
|
||||
!project || projectSelectSchema.safeParse(project).success,
|
||||
{
|
||||
message: 'Invalid lastDeployment'
|
||||
}
|
||||
)
|
||||
.transform((project): any => {
|
||||
if (!project) return undefined
|
||||
return projectSelectSchema.parse(project)
|
||||
})
|
||||
.optional()
|
||||
|
|
|
@ -237,12 +237,14 @@ export const projectSelectSchema = createSelectSchema(projects, {
|
|||
.any()
|
||||
.refine(
|
||||
(deployment): boolean =>
|
||||
deploymentSelectSchema.safeParse(deployment).success,
|
||||
!deployment || deploymentSelectSchema.safeParse(deployment).success,
|
||||
{
|
||||
message: 'Invalid lastPublishedDeployment'
|
||||
}
|
||||
)
|
||||
.transform((deployment): any => {
|
||||
if (!deployment) return undefined
|
||||
|
||||
return deploymentSelectSchema.parse(deployment)
|
||||
})
|
||||
.optional(),
|
||||
|
@ -252,12 +254,13 @@ export const projectSelectSchema = createSelectSchema(projects, {
|
|||
.any()
|
||||
.refine(
|
||||
(deployment): boolean =>
|
||||
deploymentSelectSchema.safeParse(deployment).success,
|
||||
!deployment || deploymentSelectSchema.safeParse(deployment).success,
|
||||
{
|
||||
message: 'Invalid lastDeployment'
|
||||
}
|
||||
)
|
||||
.transform((deployment): any => {
|
||||
if (!deployment) return undefined
|
||||
return deploymentSelectSchema.parse(deployment)
|
||||
})
|
||||
.optional()
|
||||
|
|
|
@ -163,27 +163,31 @@ export function MarketplaceProjectIndex({
|
|||
Pricing Plans
|
||||
</h2>
|
||||
|
||||
{project.lastPublishedDeployment!.pricingPlans.map((plan) => (
|
||||
<div key={plan.slug} className='grid gap-4'>
|
||||
<h3 className='text-center text-balance leading-snug md:leading-none text-xl font-bold'>
|
||||
{plan.name}
|
||||
</h3>
|
||||
<div className='flex gap-8'>
|
||||
{project.lastPublishedDeployment!.pricingPlans.map((plan) => (
|
||||
<div key={plan.slug} className='flex flex-col gap-4'>
|
||||
<h3 className='text-center text-balance leading-snug md:leading-none text-xl font-bold'>
|
||||
{plan.name}
|
||||
</h3>
|
||||
|
||||
<pre className='max-w-lg'>{JSON.stringify(plan, null, 2)}</pre>
|
||||
<pre className='max-w-lg'>
|
||||
{JSON.stringify(plan, null, 2)}
|
||||
</pre>
|
||||
|
||||
<Button
|
||||
onClick={() => onSubscribe(plan.slug)}
|
||||
// TODO: handle free plans correctly
|
||||
disabled={consumer?.plan === plan.slug}
|
||||
>
|
||||
{consumer?.plan === plan.slug ? (
|
||||
<span>Currently subscribed to "{plan.name}"</span>
|
||||
) : (
|
||||
<span>Subscribe to "{plan.name}"</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
<Button
|
||||
onClick={() => onSubscribe(plan.slug)}
|
||||
// TODO: handle free plans correctly
|
||||
disabled={consumer?.plan === plan.slug}
|
||||
>
|
||||
{consumer?.plan === plan.slug ? (
|
||||
<span>Currently subscribed to "{plan.name}"</span>
|
||||
) : (
|
||||
<span>Subscribe to "{plan.name}"</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -80,5 +80,82 @@ export default defineConfig({
|
|||
inputSchemaAdditionalProperties: false,
|
||||
outputSchemaAdditionalProperties: false
|
||||
}
|
||||
],
|
||||
pricingPlans: [
|
||||
{
|
||||
name: 'Free',
|
||||
slug: 'free',
|
||||
lineItems: [
|
||||
{
|
||||
slug: 'base',
|
||||
usageType: 'licensed',
|
||||
amount: 0
|
||||
},
|
||||
{
|
||||
slug: 'requests',
|
||||
usageType: 'metered',
|
||||
billingScheme: 'per_unit',
|
||||
unitAmount: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Starter',
|
||||
slug: 'starter',
|
||||
lineItems: [
|
||||
{
|
||||
slug: 'base',
|
||||
usageType: 'licensed',
|
||||
amount: 999 // $9.99 USD
|
||||
},
|
||||
{
|
||||
slug: 'requests',
|
||||
usageType: 'metered',
|
||||
billingScheme: 'tiered',
|
||||
tiersMode: 'volume',
|
||||
// free for first 1000 requests per month
|
||||
// then $0.00053 USD for unlimited further requests that month
|
||||
tiers: [
|
||||
{
|
||||
upTo: 1000,
|
||||
unitAmount: 0
|
||||
},
|
||||
{
|
||||
upTo: 'inf',
|
||||
unitAmount: 0.053
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Pro',
|
||||
slug: 'pro',
|
||||
lineItems: [
|
||||
{
|
||||
slug: 'base',
|
||||
usageType: 'licensed',
|
||||
amount: 2999 // $29.99 USD
|
||||
},
|
||||
{
|
||||
slug: 'requests',
|
||||
usageType: 'metered',
|
||||
billingScheme: 'tiered',
|
||||
tiersMode: 'volume',
|
||||
// free for first 10000 requests per month
|
||||
// then $0.00049 USD for unlimited further requests that month
|
||||
tiers: [
|
||||
{
|
||||
upTo: 10_000,
|
||||
unitAmount: 0
|
||||
},
|
||||
{
|
||||
upTo: 'inf',
|
||||
unitAmount: 0.049
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
|
@ -75,7 +75,7 @@ export function errorHandler(
|
|||
console.error('Error Sentry.captureException failed', err, err_)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (status !== 404) {
|
||||
logger.warn(status, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
- consider a PrettyJson component which displays json but links to resources
|
||||
- stripe
|
||||
- stripe checkout for changing plans? (need to at least be able to upgrade)
|
||||
- stripe billing portal
|
||||
- should we bypass stripe for `free` plans to increase conversions?
|
||||
- handle browser back/forward with `?next=`
|
||||
- add some social proof to signup page
|
||||
|
|
Ładowanie…
Reference in New Issue