mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
chore: Remove dangling dependencies and files (#19785)
* Delete probably unneeded files. * Remove unused deps.
This commit is contained in:
1 parent
b5b26fc110
commit
563ef1cff2
48 files changed
+1
-3492
No files matched your search
@@ -1,165 +0,0 @@
|
||||
// [Joshen] Maybe shift this into shared-types repo or something?
|
||||
// This isn't typed completely properly as I'm not too sure myself
|
||||
export interface AuthConfig {
|
||||
id: number
|
||||
project_id: number
|
||||
updated_at: string
|
||||
|
||||
DISABLE_SIGNUP: boolean
|
||||
SECURITY_MANUAL_LINKING_ENABLED: boolean
|
||||
EXTERNAL_EMAIL_ENABLED: boolean
|
||||
EXTERNAL_PHONE_ENABLED: boolean
|
||||
|
||||
EXTERNAL_APPLE_ENABLED: boolean
|
||||
EXTERNAL_APPLE_CLIENT_ID: string | null
|
||||
EXTERNAL_APPLE_SECRET: string | null
|
||||
|
||||
EXTERNAL_AZURE_ENABLED: boolean
|
||||
EXTERNAL_AZURE_URL: string | null
|
||||
EXTERNAL_AZURE_CLIENT_ID: string | null
|
||||
EXTERNAL_AZURE_SECRET: string | null
|
||||
|
||||
EXTERNAL_BITBUCKET_ENABLED: boolean
|
||||
EXTERNAL_BITBUCKET_CLIENT_ID: string | null
|
||||
EXTERNAL_BITBUCKET_SECRET: string | null
|
||||
|
||||
EXTERNAL_DISCORD_ENABLED: boolean
|
||||
EXTERNAL_DISCORD_CLIENT_ID: string | null
|
||||
EXTERNAL_DISCORD_SECRET: string | null
|
||||
|
||||
EXTERNAL_FACEBOOK_ENABLED: boolean
|
||||
EXTERNAL_FACEBOOK_CLIENT_ID: string | null
|
||||
EXTERNAL_FACEBOOK_SECRET: string | null
|
||||
|
||||
EXTERNAL_FIGMA_ENABLED: boolean
|
||||
EXTERNAL_FIGMA_CLIENT_ID: string | null
|
||||
EXTERNAL_FIGMA_SECRET: string | null
|
||||
|
||||
EXTERNAL_GITHUB_ENABLED: false
|
||||
EXTERNAL_GITHUB_CLIENT_ID: string | null
|
||||
EXTERNAL_GITHUB_SECRET: string | null
|
||||
|
||||
EXTERNAL_GITLAB_ENABLED: boolean
|
||||
EXTERNAL_GITLAB_CLIENT_ID: string | null
|
||||
EXTERNAL_GITLAB_REDIRECT_URI: string | null
|
||||
EXTERNAL_GITLAB_SECRET: string | null
|
||||
|
||||
EXTERNAL_GOOGLE_ENABLED: boolean
|
||||
EXTERNAL_GOOGLE_CLIENT_ID: string | null
|
||||
EXTERNAL_GOOGLE_SECRET: string | null
|
||||
|
||||
EXTERNAL_KEYCLOAK_ENABLED: boolean
|
||||
EXTERNAL_KEYCLOAK_CLIENT_ID: string | null
|
||||
EXTERNAL_KEYCLOAK_SECRET: string | null
|
||||
EXTERNAL_KEYCLOAK_URL: string | null
|
||||
|
||||
EXTERNAL_LINKEDIN_ENABLED: boolean
|
||||
EXTERNAL_LINKEDIN_CLIENT_ID: string | null
|
||||
EXTERNAL_LINKEDIN_SECRET: string | null
|
||||
|
||||
EXTERNAL_LINKEDIN_OIDC_ENABLED: boolean
|
||||
EXTERNAL_LINKEDIN_OIDC_CLIENT_ID: string | null
|
||||
EXTERNAL_LINKEDIN_OIDC_SECRET: string | null
|
||||
|
||||
EXTERNAL_NOTION_ENABLED: boolean
|
||||
EXTERNAL_NOTION_CLIENT_ID: string | null
|
||||
EXTERNAL_NOTION_SECRET: string | null
|
||||
|
||||
EXTERNAL_SLACK_ENABLED: boolean
|
||||
EXTERNAL_SLACK_CLIENT_ID: string | null
|
||||
EXTERNAL_SLACK_SECRET: string | null
|
||||
|
||||
EXTERNAL_SPOTIFY_ENABLED: boolean
|
||||
EXTERNAL_SPOTIFY_CLIENT_ID: string | null
|
||||
EXTERNAL_SPOTIFY_SECRET: string | null
|
||||
|
||||
EXTERNAL_TWITCH_ENABLED: boolean
|
||||
EXTERNAL_TWITCH_CLIENT_ID: string | null
|
||||
EXTERNAL_TWITCH_SECRET: string | null
|
||||
|
||||
EXTERNAL_TWITTER_ENABLED: boolean
|
||||
EXTERNAL_TWITTER_CLIENT_ID: string | null
|
||||
EXTERNAL_TWITTER_SECRET: string | null
|
||||
|
||||
EXTERNAL_WORKOS_ENABLED: boolean
|
||||
EXTERNAL_WORKOS_CLIENT_ID: string | null
|
||||
EXTERNAL_WORKOS_SECRET: string | null
|
||||
EXTERNAL_WORKOS_URL: string | null
|
||||
|
||||
EXTERNAL_ZOOM_ENABLED: boolean
|
||||
EXTERNAL_ZOOM_CLIENT_ID: string | null
|
||||
EXTERNAL_ZOOM_SECRET: string | null
|
||||
|
||||
JWT_AUD: 'authenticated' | string
|
||||
JWT_DEFAULT_GROUP_NAME: 'authenticated' | string
|
||||
JWT_EXP: number
|
||||
|
||||
MAILER_AUTOCONFIRM: boolean
|
||||
MAILER_OTP_EXP: number
|
||||
MAILER_SECURE_EMAIL_CHANGE_ENABLED: boolean
|
||||
MAILER_SUBJECTS_CONFIRMATION: string
|
||||
MAILER_SUBJECTS_EMAIL_CHANGE: string
|
||||
MAILER_SUBJECTS_INVITE: string
|
||||
MAILER_SUBJECTS_MAGIC_LINK: string
|
||||
MAILER_SUBJECTS_RECOVERY: string
|
||||
MAILER_TEMPLATES_CONFIRMATION: string | null
|
||||
MAILER_TEMPLATES_CONFIRMATION_CONTENT: string
|
||||
MAILER_TEMPLATES_EMAIL_CHANGE: string | null
|
||||
MAILER_TEMPLATES_EMAIL_CHANGE_CONTENT: string
|
||||
MAILER_TEMPLATES_INVITE: string | null
|
||||
MAILER_TEMPLATES_INVITE_CONTENT: string
|
||||
MAILER_TEMPLATES_MAGIC_LINK: string | null
|
||||
MAILER_TEMPLATES_MAGIC_LINK_CONTENT: string
|
||||
MAILER_TEMPLATES_RECOVERY: string | null
|
||||
MAILER_TEMPLATES_RECOVERY_CONTENT: string
|
||||
MAILER_URLPATHS_CONFIRMATION: string
|
||||
MAILER_URLPATHS_EMAIL_CHANGE: string
|
||||
MAILER_URLPATHS_INVITE: string
|
||||
MAILER_URLPATHS_RECOVERY: string
|
||||
|
||||
OPERATOR_TOKEN: string | null
|
||||
PASSWORD_MIN_LENGTH: number
|
||||
RATE_LIMIT_EMAIL_SENT: number
|
||||
RATE_LIMIT_SMS_SENT: number
|
||||
RATE_LIMIT_HEADER: string | null
|
||||
RATE_LIMIT_TOKEN_REFRESH: number
|
||||
RATE_LIMIT_VERIFY: number
|
||||
REFRESH_TOKEN_ROTATION_ENABLED: boolean
|
||||
|
||||
SECURITY_CAPTCHA_ENABLED: boolean
|
||||
SECURITY_CAPTCHA_PROVIDER: 'hcaptcha' | 'turnstile' | string
|
||||
SECURITY_CAPTCHA_SECRET: string
|
||||
SECURITY_REFRESH_TOKEN_REUSE_INTERVAL: number
|
||||
SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION: boolean
|
||||
|
||||
SITE_URL: string
|
||||
SMS_AUTOCONFIRM: boolean
|
||||
SMS_MAX_FREQUENCY: number
|
||||
SMS_MESSAGEBIRD_ACCESS_KEY: string
|
||||
SMS_MESSAGEBIRD_ORIGINATOR: string
|
||||
SMS_OTP_EXP: number
|
||||
SMS_OTP_LENGTH: number
|
||||
SMS_PROVIDER: 'twilio' | string
|
||||
SMS_TEMPLATE: string
|
||||
SMS_TEXTLOCAL_API_KEY: string
|
||||
SMS_TEXTLOCAL_SENDER: string
|
||||
SMS_TWILIO_ACCOUNT_SID: string
|
||||
SMS_TWILIO_AUTH_TOKEN: string
|
||||
SMS_TWILIO_CONTENT_SID: string
|
||||
SMS_TWILIO_MESSAGE_SERVICE_SID: string
|
||||
SMS_TWILIO_VERIFY_ACCOUNT_SID: string
|
||||
SMS_TWILIO_VERIFY_AUTH_TOKEN: string
|
||||
SMS_TWILIO_VERIFY_MESSAGE_SERVICE_SID: string
|
||||
SMS_VONAGE_API_KEY: string
|
||||
SMS_VONAGE_API_SECRET: string
|
||||
SMS_VONAGE_FROM: string
|
||||
SMTP_ADMIN_EMAIL: string | null
|
||||
SMTP_HOST: string | null
|
||||
SMTP_MAX_FREQUENCY: number
|
||||
SMTP_PASS: string | null
|
||||
SMTP_PASS_ENCRYPTED: string | null
|
||||
SMTP_PORT: number | string | null
|
||||
SMTP_SENDER_NAME: string | null
|
||||
SMTP_USER: string | null
|
||||
URI_ALLOW_LIST: string
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
// [Joshen] Probably need to centralize this value somewhere as it needs to be used
|
||||
// by email notifications as well
|
||||
export const USAGE_APPROACHING_THRESHOLD = 0.8
|
||||
|
||||
export const BILLING_BREAKDOWN_METRICS = [
|
||||
{
|
||||
key: 'db_size',
|
||||
name: 'Database space',
|
||||
units: 'bytes',
|
||||
anchor: 'dbSize',
|
||||
metric: 'DATABASE_SIZE',
|
||||
category: 'Database',
|
||||
unitName: 'GB',
|
||||
},
|
||||
{
|
||||
key: 'db_egress',
|
||||
name: 'Database egress',
|
||||
units: 'bytes',
|
||||
anchor: 'egress',
|
||||
metric: 'DATABASE_EGRESS',
|
||||
category: 'Database',
|
||||
unitName: 'GB',
|
||||
},
|
||||
{
|
||||
key: 'monthly_active_users',
|
||||
name: 'Active users',
|
||||
units: 'absolute',
|
||||
anchor: 'mau',
|
||||
metric: 'MONTHLY_ACTIVE_USERS',
|
||||
category: 'Authentication',
|
||||
unitName: 'MAU',
|
||||
},
|
||||
{
|
||||
key: 'monthly_active_sso_users',
|
||||
name: 'Active SSO users',
|
||||
units: 'absolute',
|
||||
anchor: 'mauSso',
|
||||
metric: 'MONTHLY_ACTIVE_SSO_USERS',
|
||||
category: 'Authentication',
|
||||
unitName: 'MAU',
|
||||
},
|
||||
{
|
||||
key: 'storage_size',
|
||||
name: 'Storage space',
|
||||
units: 'bytes',
|
||||
anchor: 'storageSize',
|
||||
metric: 'STORAGE_SIZE',
|
||||
category: 'Storage',
|
||||
unitName: 'GB',
|
||||
},
|
||||
{
|
||||
key: 'storage_egress',
|
||||
name: 'Storage egress',
|
||||
units: 'bytes',
|
||||
anchor: 'storageEgress',
|
||||
metric: 'STORAGE_EGRESS',
|
||||
category: 'Storage',
|
||||
unitName: 'GB',
|
||||
},
|
||||
{
|
||||
key: 'storage_image_render_count',
|
||||
name: 'Storage Image Transformations',
|
||||
units: 'absolute',
|
||||
anchor: 'storageImageTransformations',
|
||||
metric: 'STORAGE_IMAGES_TRANSFORMED',
|
||||
category: 'Storage',
|
||||
unitName: 'image',
|
||||
},
|
||||
{
|
||||
key: 'realtime_peak_connection',
|
||||
name: 'Realtime peak connections',
|
||||
units: 'absolute',
|
||||
anchor: 'realtimePeakConnections',
|
||||
metric: 'REALTIME_PEAK_CONNECTIONS',
|
||||
category: 'Realtime',
|
||||
unitName: 'connection',
|
||||
},
|
||||
{
|
||||
key: 'realtime_message_count',
|
||||
name: 'Realtime messages',
|
||||
units: 'absolute',
|
||||
anchor: 'realtimeMessageCount',
|
||||
metric: 'REALTIME_MESSAGE_COUNT',
|
||||
category: 'Realtime',
|
||||
unitName: 'message',
|
||||
},
|
||||
{
|
||||
key: 'func_invocations',
|
||||
name: 'Edge Function invocations',
|
||||
units: 'absolute',
|
||||
anchor: 'funcInvocations',
|
||||
metric: 'FUNCTION_INVOCATIONS',
|
||||
category: 'Edge Functions',
|
||||
unitName: 'invocation',
|
||||
},
|
||||
{
|
||||
key: 'func_count',
|
||||
name: 'Edge Functions',
|
||||
units: 'absolute',
|
||||
anchor: 'funcCount',
|
||||
metric: 'FUNCTION_COUNT',
|
||||
category: 'Edge Functions',
|
||||
unitName: 'function',
|
||||
},
|
||||
] as const
|
||||
@@ -1,30 +0,0 @@
|
||||
// Converts a list of single object, into a single object
|
||||
// e.g [{ name: 'name1', value: 'value1' }, { name: 'name2', value: 'value2' }]
|
||||
// -> { name1: 'value1', name2: 'value2' }
|
||||
export const formatArguments = (args: { name: string; value: string }[]) => {
|
||||
const res: any = {}
|
||||
args.forEach((args) => {
|
||||
res[args.name] = args.value
|
||||
})
|
||||
return JSON.stringify(res)
|
||||
}
|
||||
|
||||
/**
|
||||
* convert "{\"Content-type\":\"application/json\"}"
|
||||
* to {value: [{name: 'search_path', value: 'auth, public'}]}
|
||||
*/
|
||||
|
||||
export const convertKeyValue = (value: string) => {
|
||||
const temp = []
|
||||
if (value) {
|
||||
const obj = JSON.parse(value)
|
||||
for (var key in obj) {
|
||||
temp.push({ name: key, value: obj[key] })
|
||||
}
|
||||
}
|
||||
return { value: temp }
|
||||
}
|
||||
|
||||
export const hasWhitespace = (value: string) => {
|
||||
return /\s/.test(value)
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
const NoDescription = () => {
|
||||
return (
|
||||
<p className="text-gray-300 text-sm">
|
||||
No description provided.
|
||||
<br />
|
||||
Hint: you can create a custom description by adding a "comment" to this item in your database.
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
export default NoDescription
|
||||
@@ -1,326 +0,0 @@
|
||||
export const LOGS_DATA = [
|
||||
{
|
||||
id: 1,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 256,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 256,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: '/readededeaded/functions/hello-world',
|
||||
method: 'POST',
|
||||
runtime: 'Node14',
|
||||
memory: 512,
|
||||
created_at: 1646524256,
|
||||
user_agent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
|
||||
memory_used: '113',
|
||||
init_duration: '431.44',
|
||||
duration: '1394.57 ms',
|
||||
edge_status: '200',
|
||||
function_status: '200',
|
||||
},
|
||||
]
|
||||
|
||||
export const REQUEST_SAMPLE = {
|
||||
custom_fields: {
|
||||
'0': {
|
||||
name: 'Project name',
|
||||
value: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const RESPONSE_SAMPLE = [
|
||||
{
|
||||
id: 'in_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
object: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
account_country: 'US',
|
||||
account_name: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
account_tax_ids: null,
|
||||
amount_due: 0,
|
||||
amount_paid: 0,
|
||||
amount_remaining: 0,
|
||||
application_fee_amount: null,
|
||||
attempt_count: 0,
|
||||
attempted: false,
|
||||
auto_advance: true,
|
||||
automatic_tax: {
|
||||
enabled: false,
|
||||
status: null,
|
||||
},
|
||||
billing_reason: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
charge: null,
|
||||
collection_method: 'charge_automatically',
|
||||
created: 1646526032,
|
||||
currency: 'usd',
|
||||
custom_fields: [
|
||||
{
|
||||
name: 'Project name',
|
||||
value: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
},
|
||||
],
|
||||
customer: 'cus_in_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
customer_address: null,
|
||||
customer_email: 'in_1a1a1a1a1a1a1a1a1a1a1a@gmail.com',
|
||||
customer_name: null,
|
||||
customer_phone: null,
|
||||
customer_shipping: null,
|
||||
customer_tax_exempt: 'none',
|
||||
customer_tax_ids: [],
|
||||
default_payment_method: null,
|
||||
default_source: null,
|
||||
default_tax_rates: [],
|
||||
description: null,
|
||||
discount: null,
|
||||
discounts: [],
|
||||
due_date: null,
|
||||
ending_balance: null,
|
||||
footer: null,
|
||||
hosted_invoice_url: null,
|
||||
invoice_pdf: null,
|
||||
last_finalization_error: null,
|
||||
lines: {
|
||||
object: 'list',
|
||||
data: [
|
||||
{
|
||||
id: 'il_in_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
object: 'line_item',
|
||||
amount: 0,
|
||||
currency: 'usd',
|
||||
description: '1 × Free tier (at $0.00 / month)',
|
||||
discount_amounts: [],
|
||||
discountable: true,
|
||||
discounts: [],
|
||||
livemode: true,
|
||||
metadata: {
|
||||
project_id: '29167',
|
||||
project_ref: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
project_name: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
organization_id: '1a1a1a1a1a1a1a1a1a1a1a',
|
||||
organization_slug:
|
||||
'1a1a1a1a1a1a1a1a1a1a1a-1a1a1a1a1a1a1a1a1a1a1a-1a1a1a1a1a1a1a1a1a1a1a',
|
||||
},
|
||||
period: {
|
||||
end: 1649204401,
|
||||
start: 1646526001,
|
||||
},
|
||||
plan: {
|
||||
id: 'price_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
object: 'plan',
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 0,
|
||||
amount_decimal: '0',
|
||||
billing_scheme: 'per_unit',
|
||||
created: 1615645622,
|
||||
currency: 'usd',
|
||||
interval: 'month',
|
||||
interval_count: 1,
|
||||
livemode: true,
|
||||
metadata: {
|
||||
price: '0000',
|
||||
},
|
||||
nickname: null,
|
||||
product: 'prod_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: 'licensed',
|
||||
},
|
||||
price: {
|
||||
id: 'price_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
object: 'price',
|
||||
active: true,
|
||||
billing_scheme: 'per_unit',
|
||||
created: 1615645622,
|
||||
currency: 'usd',
|
||||
livemode: true,
|
||||
lookup_key: null,
|
||||
metadata: {
|
||||
price: '0000',
|
||||
},
|
||||
nickname: null,
|
||||
product: 'prod_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: 'month',
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: 'licensed',
|
||||
},
|
||||
tax_behavior: 'unspecified',
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: 'recurring',
|
||||
unit_amount: 0,
|
||||
unit_amount_decimal: '0',
|
||||
},
|
||||
proration: false,
|
||||
proration_details: {
|
||||
credited_items: null,
|
||||
},
|
||||
quantity: 1,
|
||||
subscription: 'sub_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
subscription_item: 'si_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
tax_amounts: [],
|
||||
tax_rates: [],
|
||||
type: 'subscription',
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
total_count: 1,
|
||||
url: '/v1/invoices/in_1a1a1a1a1a1a1a1a1a1a1a/lines',
|
||||
},
|
||||
livemode: true,
|
||||
metadata: {},
|
||||
next_payment_attempt: 1646529632,
|
||||
number: null,
|
||||
on_behalf_of: null,
|
||||
paid: false,
|
||||
paid_out_of_band: false,
|
||||
payment_intent: null,
|
||||
payment_settings: {
|
||||
payment_method_options: null,
|
||||
payment_method_types: null,
|
||||
},
|
||||
period_end: 1646526001,
|
||||
period_start: 1644106801,
|
||||
post_payment_credit_notes_amount: 0,
|
||||
pre_payment_credit_notes_amount: 0,
|
||||
quote: null,
|
||||
receipt_number: null,
|
||||
starting_balance: 0,
|
||||
statement_descriptor: null,
|
||||
status: 'draft',
|
||||
status_transitions: {
|
||||
finalized_at: null,
|
||||
marked_uncollectible_at: null,
|
||||
paid_at: null,
|
||||
voided_at: null,
|
||||
},
|
||||
subscription: 'sub_1a1a1a1a1a1a1a1a1a1a1a',
|
||||
subtotal: 0,
|
||||
tax: null,
|
||||
test_clock: null,
|
||||
total: 0,
|
||||
total_discount_amounts: [],
|
||||
total_tax_amounts: [],
|
||||
transfer_data: null,
|
||||
webhooks_delivered_at: null,
|
||||
},
|
||||
]
|
||||
@@ -1,4 +0,0 @@
|
||||
export interface EndpointResponse<T> {
|
||||
result: Array<T>
|
||||
error: Object
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import { noop } from 'lodash'
|
||||
import { Badge, Button } from 'ui'
|
||||
|
||||
import { Project } from 'types'
|
||||
|
||||
interface PausedProjectCardProps {
|
||||
project: Project
|
||||
onSelectRestore: () => void
|
||||
onSelectDelete: () => void
|
||||
}
|
||||
|
||||
const PausedProjectCard = ({
|
||||
project,
|
||||
onSelectRestore = noop,
|
||||
onSelectDelete = noop,
|
||||
}: PausedProjectCardProps) => {
|
||||
return (
|
||||
<li className="col-span-1 flex rounded-md shadow-sm">
|
||||
<a className="col-span-3 w-full md:col-span-1 ">
|
||||
<div
|
||||
className={[
|
||||
'bg-surface-100',
|
||||
'hover:bg-background',
|
||||
'border border-strong',
|
||||
'hover:border-stronger',
|
||||
'h-32 rounded p-4',
|
||||
'flex flex-col justify-between transition duration-150 ease-in-out',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="flex items-center justify-between space-x-2">
|
||||
<h5 className="m-0 truncate">{project.name}</h5>
|
||||
<Badge color="yellow" dot>
|
||||
Paused
|
||||
</Badge>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button size="tiny" onClick={() => onSelectRestore()}>
|
||||
Restore
|
||||
</Button>
|
||||
<Button size="tiny" type="outline" onClick={() => onSelectDelete()}>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default PausedProjectCard
|
||||
@@ -1,348 +0,0 @@
|
||||
import * as Tooltip from '@radix-ui/react-tooltip'
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import { useParams } from 'common'
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
Alert,
|
||||
Badge,
|
||||
Button,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
IconCreditCard,
|
||||
IconMoreHorizontal,
|
||||
IconPlus,
|
||||
IconX,
|
||||
Input,
|
||||
Modal,
|
||||
} from 'ui'
|
||||
|
||||
import AlertError from 'components/ui/AlertError'
|
||||
import NoPermission from 'components/ui/NoPermission'
|
||||
import Panel from 'components/ui/Panel'
|
||||
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { useOrganizationCustomerProfileQuery } from 'data/organizations/organization-customer-profile-query'
|
||||
import { useOrganizationCustomerProfileUpdateMutation } from 'data/organizations/organization-customer-profile-update-mutation'
|
||||
import { useOrganizationPaymentMethodDeleteMutation } from 'data/organizations/organization-payment-method-delete-mutation'
|
||||
import { useOrganizationPaymentMethodsQuery } from 'data/organizations/organization-payment-methods-query'
|
||||
import { useCheckPermissions, useStore } from 'hooks'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { getURL } from 'lib/helpers'
|
||||
import AddNewPaymentMethodModal from 'components/interfaces/Billing/Payment/AddNewPaymentMethodModal'
|
||||
|
||||
const PaymentMethods = () => {
|
||||
const { ui } = useStore()
|
||||
const { slug } = useParams()
|
||||
|
||||
const [selectedMethodForDefault, setSelectedMethodForDefault] = useState<any>()
|
||||
const [selectedMethodToDelete, setSelectedMethodToDelete] = useState<any>()
|
||||
const [showAddPaymentMethodModal, setShowAddPaymentMethodModal] = useState(false)
|
||||
|
||||
const { mutate: updateCustomerProfile, isLoading: isUpdating } =
|
||||
useOrganizationCustomerProfileUpdateMutation({
|
||||
onSuccess: (updatedCustomer) => {
|
||||
setSelectedMethodForDefault(undefined)
|
||||
ui.setNotification({
|
||||
category: 'success',
|
||||
message: 'Successfully updated default payment method',
|
||||
})
|
||||
},
|
||||
onError: (error) => {
|
||||
ui.setNotification({
|
||||
category: 'error',
|
||||
message: `Failed to make payment method default: ${error.message}`,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const { mutate: deletePaymentMethod, isLoading: isDeleting } =
|
||||
useOrganizationPaymentMethodDeleteMutation({
|
||||
onSuccess: () => {
|
||||
setSelectedMethodToDelete(undefined)
|
||||
ui.setNotification({ category: 'success', message: 'Successfully deleted payment method' })
|
||||
},
|
||||
})
|
||||
|
||||
const { data: customer } = useOrganizationCustomerProfileQuery({ slug })
|
||||
|
||||
const {
|
||||
data,
|
||||
error: paymentMethodsError,
|
||||
refetch: refetchPaymentMethods,
|
||||
isLoading: isLoadingPaymentMethods,
|
||||
isError: isErrorPaymentMethods,
|
||||
isSuccess: isSuccessPaymentMethods,
|
||||
} = useOrganizationPaymentMethodsQuery({ slug })
|
||||
const paymentMethods = data || []
|
||||
|
||||
const defaultPaymentMethod = customer?.invoice_settings?.default_payment_method ?? ''
|
||||
|
||||
const canReadPaymentMethods = useCheckPermissions(
|
||||
PermissionAction.BILLING_READ,
|
||||
'stripe.payment_methods'
|
||||
)
|
||||
const canUpdatePaymentMethods = useCheckPermissions(
|
||||
PermissionAction.BILLING_WRITE,
|
||||
'stripe.payment_methods'
|
||||
)
|
||||
|
||||
const onConfirmMakeDefaultPaymentMethod = () => {
|
||||
if (!slug) return console.error('Slug is required')
|
||||
updateCustomerProfile({
|
||||
slug,
|
||||
invoice_settings: {
|
||||
default_payment_method: selectedMethodForDefault.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const onConfirmDetachPaymentMethod = () => {
|
||||
if (!slug) return console.error('Slug is required')
|
||||
deletePaymentMethod({ slug, cardId: selectedMethodToDelete.id })
|
||||
}
|
||||
|
||||
const onLocalPaymentMethodAdded = () => {
|
||||
setShowAddPaymentMethodModal(false)
|
||||
ui.setNotification({ category: 'success', message: 'Successfully added new payment method' })
|
||||
return refetchPaymentMethods()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-2 -mb-8">
|
||||
<div>
|
||||
<h4>Payment methods</h4>
|
||||
<p className="text-sm opacity-50">
|
||||
When adding a new payment method, either remove the old one or go to your projects'
|
||||
subscription to explicitly update the payment method. Marking a payment method as
|
||||
"default" is only relevant for new projects or if there are no other payment methods on
|
||||
your account.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{!isLoadingPaymentMethods && !canReadPaymentMethods && (
|
||||
<Panel>
|
||||
<NoPermission resourceText="view this organization's payment methods" />
|
||||
</Panel>
|
||||
)}
|
||||
|
||||
{isLoadingPaymentMethods && <GenericSkeletonLoader />}
|
||||
|
||||
{isErrorPaymentMethods && (
|
||||
<AlertError error={paymentMethodsError} subject="Failed to retrieve payment methods" />
|
||||
)}
|
||||
|
||||
{isSuccessPaymentMethods && (
|
||||
<Panel
|
||||
footer={
|
||||
<div className="flex w-full justify-between">
|
||||
{!canUpdatePaymentMethods ? (
|
||||
<p className="text-sm text-foreground-light">
|
||||
You need additional permissions to manage this organization's payment methods
|
||||
</p>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
<div>
|
||||
<Button
|
||||
key="panel-footer"
|
||||
type="default"
|
||||
icon={<IconPlus />}
|
||||
disabled={!canUpdatePaymentMethods}
|
||||
onClick={() => setShowAddPaymentMethodModal(true)}
|
||||
>
|
||||
Add new card
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{paymentMethods.length >= 1 ? (
|
||||
<Panel.Content>
|
||||
<div className="space-y-2">
|
||||
{paymentMethods.map((paymentMethod: any) => {
|
||||
const isDefault = paymentMethod.id === defaultPaymentMethod
|
||||
return (
|
||||
<div key={paymentMethod.id} className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-8">
|
||||
<img
|
||||
alt="Credit card brand"
|
||||
src={`${BASE_PATH}/img/payment-methods/${paymentMethod.card.brand
|
||||
.replace(' ', '-')
|
||||
.toLowerCase()}.png`}
|
||||
width="32"
|
||||
/>
|
||||
<Input
|
||||
readOnly
|
||||
className="w-64"
|
||||
size="small"
|
||||
value={`•••• •••• •••• ${paymentMethod.card.last4}`}
|
||||
/>
|
||||
{isDefault ? (
|
||||
<Badge color="gray">Default</Badge>
|
||||
) : (
|
||||
<div className="opacity-0">
|
||||
<Badge color="gray">Default</Badge>
|
||||
</div>
|
||||
)}
|
||||
<p className="text-sm tabular-nums">
|
||||
Expires: {paymentMethod.card.exp_month}/{paymentMethod.card.exp_year}
|
||||
</p>
|
||||
</div>
|
||||
{canUpdatePaymentMethods && (
|
||||
<>
|
||||
{isDefault ? (
|
||||
<Tooltip.Root delayDuration={0}>
|
||||
<Tooltip.Trigger asChild>
|
||||
<Button disabled type="outline" icon={<IconX />} />
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content side="bottom">
|
||||
<Tooltip.Arrow className="radix-tooltip-arrow" />
|
||||
<div
|
||||
className={[
|
||||
'rounded bg-alternative py-1 px-2 leading-none shadow', // background
|
||||
'w-48 border border-background text-center', //border
|
||||
].join(' ')}
|
||||
>
|
||||
<span className="text-xs text-foreground">
|
||||
Your default payment method cannot be deleted
|
||||
</span>
|
||||
</div>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip.Root>
|
||||
) : (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
type="outline"
|
||||
loading={isLoadingPaymentMethods}
|
||||
className="hover:border-gray-500"
|
||||
>
|
||||
<IconMoreHorizontal />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
key="make-default"
|
||||
onClick={() => setSelectedMethodForDefault(paymentMethod)}
|
||||
>
|
||||
<p>Make default</p>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
key="delete-method"
|
||||
onClick={() => setSelectedMethodToDelete(paymentMethod)}
|
||||
>
|
||||
<p>Delete</p>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Panel.Content>
|
||||
) : (
|
||||
<Panel.Content>
|
||||
<div className="flex items-center space-x-2 opacity-50">
|
||||
<IconCreditCard />
|
||||
<p className="text-sm">No payment methods</p>
|
||||
</div>
|
||||
</Panel.Content>
|
||||
)}
|
||||
</Panel>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<AddNewPaymentMethodModal
|
||||
visible={showAddPaymentMethodModal}
|
||||
returnUrl={`${getURL()}/org/${slug}/billing`}
|
||||
onCancel={() => setShowAddPaymentMethodModal(false)}
|
||||
onConfirm={() => onLocalPaymentMethodAdded()}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
visible={selectedMethodForDefault !== undefined}
|
||||
size="small"
|
||||
header="Set payment method as default"
|
||||
onCancel={() => setSelectedMethodForDefault(undefined)}
|
||||
customFooter={
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="default"
|
||||
disabled={isUpdating}
|
||||
onClick={() => setSelectedMethodForDefault(undefined)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={isUpdating}
|
||||
loading={isUpdating}
|
||||
onClick={onConfirmMakeDefaultPaymentMethod}
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="py-4">
|
||||
<Modal.Content>
|
||||
<p className="text-sm">
|
||||
Confirm to set selected payment method (Ending with{' '}
|
||||
{selectedMethodForDefault?.card?.last4 ?? ''}) as the default?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
visible={selectedMethodToDelete !== undefined}
|
||||
size="medium"
|
||||
header="Delete payment method"
|
||||
onCancel={() => setSelectedMethodToDelete(undefined)}
|
||||
customFooter={
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="default"
|
||||
disabled={isDeleting}
|
||||
onClick={() => setSelectedMethodToDelete(undefined)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={isDeleting}
|
||||
loading={isDeleting}
|
||||
onClick={onConfirmDetachPaymentMethod}
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="py-4">
|
||||
<Modal.Content>
|
||||
<Alert
|
||||
withIcon
|
||||
variant="warning"
|
||||
title="This will permanently delete your payment method."
|
||||
>
|
||||
<p className="">
|
||||
Any subscription currently charging this payment method will start charging your
|
||||
default payment method.
|
||||
</p>
|
||||
</Alert>
|
||||
</Modal.Content>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PaymentMethods
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
import { useParams } from 'common'
|
||||
import { Markdown } from 'components/interfaces/Markdown'
|
||||
// import { useIntegrationsQuery } from 'data/integrations/integrations-query-org-only'
|
||||
import { useStore } from 'hooks'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { IconGitHub, IconSearch, Input, Select, SidePanel } from 'ui'
|
||||
|
||||
// TO DO
|
||||
|
||||
const GitHubRepoSelection = () => {
|
||||
const { ui } = useStore()
|
||||
const { slug } = useParams()
|
||||
// const { data } = useIntegrationsQuery({ orgSlug: slug })
|
||||
|
||||
return (
|
||||
<SidePanel
|
||||
header={'Add GitHub repository'}
|
||||
size="large"
|
||||
visible={false}
|
||||
// visible={githubConnectionConfigPanelSnapshot.visible}
|
||||
// onCancel={() => githubConnectionConfigPanelSnapshot.setVisible(false)}
|
||||
>
|
||||
<div className="my-10 flex flex-col gap-6">
|
||||
<SidePanel.Content>
|
||||
<Markdown
|
||||
content={`
|
||||
### Choose repository to connect to
|
||||
|
||||
Check the details below before proceeding
|
||||
`}
|
||||
/>
|
||||
</SidePanel.Content>
|
||||
<SidePanel.Content className="flex flex-col gap-2">
|
||||
<label className="text-sm text-foreground-lighter">GitHub scope / organization</label>
|
||||
<div className="flex gap-3 w-full">
|
||||
<Select icon={<IconGitHub />} className="w-full">
|
||||
<Select.Option value="mildtomato">MildTomato</Select.Option>
|
||||
<Select.Option value="supabase">Supabase</Select.Option>
|
||||
</Select>
|
||||
<Input autoFocus icon={<IconSearch />} className="w-full" placeholder="Search..." />
|
||||
</div>
|
||||
</SidePanel.Content>
|
||||
<SidePanel.Content>
|
||||
<ul>
|
||||
<li className="border px-10">
|
||||
{/* <IntegrationConnectionOption connection={githubIntegrations[0]} /> */}
|
||||
</li>
|
||||
</ul>
|
||||
</SidePanel.Content>
|
||||
</div>
|
||||
</SidePanel>
|
||||
)
|
||||
}
|
||||
|
||||
export default observer(GitHubRepoSelection)
|
||||
Whitespace-only changes.
@@ -1,57 +0,0 @@
|
||||
import Sparkline from 'components/ui/Charts/Sparkline'
|
||||
import React from 'react'
|
||||
|
||||
interface Props {
|
||||
value: string | number
|
||||
startingValue?: string | number
|
||||
prefix?: string
|
||||
suffix?: string
|
||||
valueFormatter?: (value: Props['value']) => string
|
||||
sparklineData?: any
|
||||
sparklineXAxis?: string
|
||||
sparklineYAxis?: string
|
||||
}
|
||||
|
||||
const Statistic: React.FC<Props> = ({
|
||||
prefix,
|
||||
suffix,
|
||||
value,
|
||||
startingValue,
|
||||
sparklineData,
|
||||
sparklineXAxis,
|
||||
sparklineYAxis,
|
||||
}) => {
|
||||
const isNumber = typeof value === 'number' && !Number.isNaN(value)
|
||||
const percentageChange =
|
||||
startingValue && isNumber ? Number(startingValue) / Number(value) - 1 : null
|
||||
const showSparkline = sparklineData && sparklineXAxis && sparklineYAxis
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="flex flex-row justify-center">
|
||||
<span>{prefix}</span>
|
||||
<span className="text-3xl text-foreground">{value}</span>
|
||||
<span>{suffix}</span>
|
||||
</div>
|
||||
{startingValue && (
|
||||
<div>
|
||||
{isNumber && percentageChange !== null && (
|
||||
<span>
|
||||
{Number(percentageChange * 100).toFixed(1)}
|
||||
{percentageChange > 0 ? 'increase' : 'decrease'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{showSparkline && (
|
||||
<Sparkline
|
||||
data={sparklineData}
|
||||
xAxisKey={sparklineXAxis}
|
||||
yAxisKey={sparklineYAxis}
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Statistic
|
||||
@@ -1,102 +0,0 @@
|
||||
import { editor } from 'monaco-editor'
|
||||
import { PropsWithChildren, useEffect, useMemo } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
|
||||
export interface InlineWidgetProps {
|
||||
/**
|
||||
* The Monaco editor instance.
|
||||
*/
|
||||
editor: editor.IStandaloneCodeEditor
|
||||
|
||||
/**
|
||||
* ID used by Monaco to reference this widget
|
||||
*/
|
||||
id: string
|
||||
|
||||
/**
|
||||
* The line number after which this zone should appear.
|
||||
* Use 0 to place a view zone before the first line number.
|
||||
*/
|
||||
afterLineNumber: number
|
||||
|
||||
/**
|
||||
* The height in lines of the view zone.
|
||||
* @default 1
|
||||
*/
|
||||
heightInLines?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an inline widget to a Monaco editor instance. Acts as a
|
||||
* container for custom widgets that are rendered inline.
|
||||
*
|
||||
* Implemented using the same techniques VS Code uses for their inline
|
||||
* widgets (such as "Go to References"), but built for React.
|
||||
* Uses a combination of a view zone and overlay widget.
|
||||
*/
|
||||
const InlineWidget = ({
|
||||
children,
|
||||
editor,
|
||||
id,
|
||||
afterLineNumber,
|
||||
heightInLines = 1,
|
||||
}: PropsWithChildren<InlineWidgetProps>) => {
|
||||
const key = `${id}-${afterLineNumber.toString()}`
|
||||
|
||||
const containerElement = useMemo(() => document.createElement('div'), [])
|
||||
|
||||
useEffect(() => {
|
||||
let zoneId: string
|
||||
let viewZoneTop = 0
|
||||
let viewZoneHeight = 0
|
||||
|
||||
const overlayWidget: editor.IOverlayWidget = {
|
||||
getId: () => id,
|
||||
getDomNode: () => containerElement,
|
||||
getPosition: () => null,
|
||||
}
|
||||
|
||||
const recalculateLayout = () => {
|
||||
const layoutInfo = editor.getLayoutInfo()
|
||||
|
||||
if (!layoutInfo) {
|
||||
return
|
||||
}
|
||||
|
||||
containerElement.style.left = `${layoutInfo.contentLeft}px`
|
||||
containerElement.style.top = `${viewZoneTop}px`
|
||||
containerElement.style.width = `${layoutInfo.width - layoutInfo.contentLeft}px`
|
||||
containerElement.style.height = `${viewZoneHeight}px`
|
||||
}
|
||||
|
||||
editor.changeViewZones((accessor) => {
|
||||
zoneId = accessor.addZone({
|
||||
afterLineNumber,
|
||||
heightInLines,
|
||||
domNode: document.createElement('div'),
|
||||
onDomNodeTop: (top) => {
|
||||
viewZoneTop = top
|
||||
recalculateLayout()
|
||||
},
|
||||
onComputedHeight: (height) => {
|
||||
viewZoneHeight = height
|
||||
recalculateLayout()
|
||||
},
|
||||
})
|
||||
|
||||
editor.addOverlayWidget(overlayWidget)
|
||||
})
|
||||
|
||||
// Remove the view zone & overlay widget on unmount
|
||||
return () => {
|
||||
editor.changeViewZones((accessor) => {
|
||||
accessor.removeZone(zoneId)
|
||||
editor.removeOverlayWidget(overlayWidget)
|
||||
})
|
||||
}
|
||||
}, [editor, id, afterLineNumber, heightInLines, containerElement])
|
||||
|
||||
return createPortal(children, containerElement, key)
|
||||
}
|
||||
|
||||
export default InlineWidget
|
||||
@@ -1,58 +0,0 @@
|
||||
import DataGrid, { Row } from 'react-data-grid'
|
||||
|
||||
interface ResultsPaneProps {
|
||||
results: any
|
||||
}
|
||||
|
||||
const ResultsPane = ({ results }: ResultsPaneProps) => {
|
||||
if (results.length === 0) {
|
||||
return (
|
||||
<div className="p-5 flex items-center space-x-2 bg-alternative">
|
||||
<p>Success. No rows returned.</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const columns = Object.keys(results[0]).map((key) => ({
|
||||
key,
|
||||
name: key,
|
||||
width: 120,
|
||||
resizable: true,
|
||||
headerRenderer: () => columnRender(key),
|
||||
formatter: ({ row }: { row: any }) => formatter(key, row),
|
||||
}))
|
||||
|
||||
const formatter = (column: any, row: any) => {
|
||||
return <span className="font-mono text-xs">{row[column] + ''}</span>
|
||||
}
|
||||
const columnRender = (name: string) => {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<p className="text-sm font-mono">{name}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rowRenderer = (props: any) => {
|
||||
const { row, viewportColumns: columns } = props
|
||||
columns.forEach((col: any) => {
|
||||
if (row[col.key] != null && typeof row[col.key] === 'object') {
|
||||
row[col.key] = JSON.stringify(row[col.key])
|
||||
}
|
||||
})
|
||||
return <Row {...props} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-grow">
|
||||
<DataGrid
|
||||
columns={columns}
|
||||
rows={results}
|
||||
renderers={{ renderRow: rowRenderer }}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ResultsPane
|
||||
@@ -1,69 +0,0 @@
|
||||
import * as Tooltip from '@radix-ui/react-tooltip'
|
||||
import { useSqlEditorStateSnapshot } from 'state/sql-editor'
|
||||
import { Button, IconMaximize2, IconMinimize2 } from 'ui'
|
||||
|
||||
export interface SizeToggleButton {
|
||||
id: string
|
||||
}
|
||||
|
||||
const SizeToggleButton = ({ id }: SizeToggleButton) => {
|
||||
const snap = useSqlEditorStateSnapshot()
|
||||
const snippet = snap.snippets[id]
|
||||
const isUtilityPanelCollapsed = (snippet?.splitSizes?.[1] ?? 0) === 0
|
||||
|
||||
const maximizeEditor = () => snap.collapseUtilityPanel(id)
|
||||
const restorePanelSize = () => snap.restoreUtilityPanel(id)
|
||||
|
||||
if (!snippet) return null
|
||||
return isUtilityPanelCollapsed ? (
|
||||
<Tooltip.Root delayDuration={0}>
|
||||
<Tooltip.Trigger asChild>
|
||||
<Button
|
||||
type="text"
|
||||
size="tiny"
|
||||
onClick={restorePanelSize}
|
||||
icon={<IconMaximize2 className="text-gray-1100" size="tiny" strokeWidth={2} />}
|
||||
/>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content side="bottom">
|
||||
<Tooltip.Arrow className="radix-tooltip-arrow" />
|
||||
<div
|
||||
className={[
|
||||
'rounded bg-alternative py-1 px-2 leading-none shadow',
|
||||
'border border-background',
|
||||
].join(' ')}
|
||||
>
|
||||
<span className="text-xs text-foreground">Show results</span>
|
||||
</div>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip.Root>
|
||||
) : (
|
||||
<Tooltip.Root delayDuration={0}>
|
||||
<Tooltip.Trigger asChild>
|
||||
<Button
|
||||
type="text"
|
||||
size="tiny"
|
||||
onClick={maximizeEditor}
|
||||
icon={<IconMinimize2 className="text-gray-1100" size="tiny" strokeWidth={2} />}
|
||||
/>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content side="bottom">
|
||||
<Tooltip.Arrow className="radix-tooltip-arrow" />
|
||||
<div
|
||||
className={[
|
||||
'rounded bg-alternative py-1 px-2 leading-none shadow',
|
||||
'border border-background',
|
||||
].join(' ')}
|
||||
>
|
||||
<span className="text-xs text-foreground">Collapse results</span>
|
||||
</div>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export default SizeToggleButton
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// [Joshen] TODO: Change the keys to enums from shared-types when ready
|
||||
|
||||
export const BREAKING_CHANGES = {
|
||||
'postgrest-v10': {
|
||||
title: 'Postgrest will be upgraded to v11',
|
||||
url: 'https://postgrest.org/en/stable/releases/v10.0.0.html#breaking-changes',
|
||||
},
|
||||
}
|
||||
|
||||
export const MANUAL_INTERVENTIONS = {
|
||||
project_unsupported_too_old: {
|
||||
title: 'Project is too old',
|
||||
description: '',
|
||||
},
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
const InstanceResizeModal = () => {
|
||||
return <div>Hello</div>
|
||||
}
|
||||
|
||||
export default InstanceResizeModal
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
import { useParams } from 'common'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Listbox, SidePanel } from 'ui'
|
||||
|
||||
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
|
||||
import { AVAILABLE_REPLICA_REGIONS } from './InstanceConfiguration.constants'
|
||||
import { AWS_REGIONS, AWS_REGIONS_DEFAULT, AWS_REGIONS_KEYS, BASE_PATH } from 'lib/constants'
|
||||
import { Database } from 'data/read-replicas/replicas-query'
|
||||
|
||||
// [Joshen] FYI this is purely for AWS only, need to update to support Fly eventually
|
||||
|
||||
interface ResizeReplicaPanelProps {
|
||||
visible: boolean
|
||||
selectedReplica?: Database
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const ResizeReplicaPanel = ({ visible, selectedReplica, onClose }: ResizeReplicaPanelProps) => {
|
||||
const { ref: projectRef } = useParams()
|
||||
const { data: addons, isSuccess } = useProjectAddonsQuery({ projectRef })
|
||||
const computeAddons =
|
||||
addons?.available_addons.find((addon) => addon.type === 'compute_instance')?.variants ?? []
|
||||
|
||||
const defaultCompute = computeAddons.find((option) => option.name === 'Small')?.identifier
|
||||
|
||||
const [selectedCompute, setSelectedCompute] = useState(defaultCompute)
|
||||
const selectedComputeMeta = computeAddons.find((addon) => addon.identifier === selectedCompute)
|
||||
const replicaRegion = AVAILABLE_REPLICA_REGIONS.find((r) =>
|
||||
selectedReplica?.region.includes(r.region)
|
||||
)
|
||||
|
||||
const onSubmit = async () => {
|
||||
console.log('Resize', { selectedCompute })
|
||||
onClose()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (visible && isSuccess) {
|
||||
}
|
||||
}, [visible, isSuccess])
|
||||
|
||||
return (
|
||||
<SidePanel
|
||||
visible={visible}
|
||||
onCancel={onClose}
|
||||
onConfirm={() => onSubmit()}
|
||||
header={`Resize read replica (ID: ${selectedReplica?.identifier})`}
|
||||
>
|
||||
<SidePanel.Content className="flex flex-col py-4 gap-y-8">
|
||||
<div className="flex flex-col gap-y-1">
|
||||
<p className="text-sm text-foreground-light">Replica is currently deployed in</p>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<img
|
||||
alt="region icon"
|
||||
className="w-7 rounded-sm"
|
||||
src={`${BASE_PATH}/img/regions/${replicaRegion?.key}.svg`}
|
||||
/>
|
||||
<p>{replicaRegion?.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
<Listbox
|
||||
size="small"
|
||||
id="compute"
|
||||
name="compute"
|
||||
value={selectedCompute}
|
||||
onChange={setSelectedCompute}
|
||||
label="Select the instance size for your read replica"
|
||||
>
|
||||
{computeAddons.map((option) => (
|
||||
<Listbox.Option key={option.identifier} label={option.name} value={option.identifier}>
|
||||
{option.name}
|
||||
</Listbox.Option>
|
||||
))}
|
||||
</Listbox>
|
||||
|
||||
<p className="text-xs text-foreground-light">
|
||||
Show some preview info on cost for deploying this replica here
|
||||
</p>
|
||||
</SidePanel.Content>
|
||||
</SidePanel>
|
||||
)
|
||||
}
|
||||
|
||||
export default ResizeReplicaPanel
|
||||
@@ -1,13 +0,0 @@
|
||||
import { QueryType } from './Logs.types'
|
||||
|
||||
const SelectionRenderHandler = ({ type }: { type: QueryType }) => {
|
||||
switch (type) {
|
||||
case 'api':
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
export default SelectionRenderHandler
|
||||
@@ -1,71 +0,0 @@
|
||||
import { noop } from 'lodash'
|
||||
import Link from 'next/link'
|
||||
import { IconArrowUpRight, IconLogOut, Menu } from 'ui'
|
||||
|
||||
interface SidebarItemProps {
|
||||
id: any
|
||||
label: string
|
||||
href?: string
|
||||
isActive?: boolean
|
||||
isSubitem?: boolean
|
||||
isExternal?: boolean
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
const SidebarItem = ({
|
||||
id,
|
||||
label,
|
||||
href,
|
||||
isActive = false,
|
||||
isSubitem = false,
|
||||
isExternal = false,
|
||||
onClick = noop,
|
||||
}: SidebarItemProps) => {
|
||||
if (href === undefined) {
|
||||
const icon = isExternal ? (
|
||||
<IconArrowUpRight size="tiny" />
|
||||
) : label === 'Logout' ? (
|
||||
<IconLogOut size="tiny" />
|
||||
) : undefined
|
||||
|
||||
return (
|
||||
<Menu.Item
|
||||
rounded
|
||||
key={id}
|
||||
style={{ marginLeft: isSubitem ? '.5rem' : '0' }}
|
||||
active={isActive}
|
||||
onClick={onClick}
|
||||
icon={icon}
|
||||
>
|
||||
{isSubitem ? <p className="text-sm">{label}</p> : label}
|
||||
</Menu.Item>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link href={href || ''} className="block" target={isExternal ? '_blank' : '_self'}>
|
||||
<button
|
||||
className={[
|
||||
'group border-default ring-foreground group-hover:border-foreground-muted',
|
||||
'flex max-w-full cursor-pointer items-center space-x-2 py-1 font-normal',
|
||||
'outline-none focus-visible:z-10 focus-visible:ring-1',
|
||||
].join(' ')}
|
||||
onClick={onClick}
|
||||
>
|
||||
{isExternal && (
|
||||
<span className="truncate text-sm text-foreground-lighter transition group-hover:text-foreground-light">
|
||||
<IconArrowUpRight size="tiny" />
|
||||
</span>
|
||||
)}
|
||||
<span
|
||||
title={label}
|
||||
className="w-full truncate text-sm text-foreground-light transition group-hover:text-foreground"
|
||||
>
|
||||
{isSubitem ? <p>{label}</p> : label}
|
||||
</span>
|
||||
</button>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default SidebarItem
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
import { useParams } from 'common'
|
||||
import { Badge, Button, Modal } from 'ui'
|
||||
|
||||
import { Integration } from 'data/integrations/integrations.types'
|
||||
import Link from 'next/link'
|
||||
|
||||
interface VercelProjectSelectionProps {
|
||||
integration?: Integration
|
||||
}
|
||||
|
||||
const VercelProjectSelection = ({ integration }: VercelProjectSelectionProps) => {
|
||||
const { ref } = useParams()
|
||||
const vercelProjectIntegration = integration?.connections.find(
|
||||
(connection) => connection.supabase_project_ref === ref
|
||||
)
|
||||
|
||||
return (
|
||||
<Modal.Content>
|
||||
<div className="space-y-1 py-6">
|
||||
<div className="flex items-center space-x-2">
|
||||
<p>Frontend Cloud Previews</p>
|
||||
<Badge color="gray">Optional</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Previews can be available by connecting your Supabase project to a Vercel project.
|
||||
</p>
|
||||
{!integration && (
|
||||
<Button asChild type="default" className="!mt-3">
|
||||
<Link
|
||||
href="https://vercel.com/integrations/supabase-v2-local"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Install Vercel Integration
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
{integration && !vercelProjectIntegration && <div>Connect project</div>}
|
||||
{integration && vercelProjectIntegration && <div>Select project</div>}
|
||||
</div>
|
||||
</Modal.Content>
|
||||
)
|
||||
}
|
||||
|
||||
export default VercelProjectSelection
|
||||
@@ -1,61 +0,0 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import {
|
||||
AccordionContent_Shadcn_,
|
||||
AccordionItem_Shadcn_,
|
||||
AccordionTrigger_Shadcn_,
|
||||
IconChevronRight,
|
||||
} from 'ui'
|
||||
|
||||
import { Project } from 'types'
|
||||
import SettingsMenuItem from './SettingsMenuItem'
|
||||
|
||||
interface ProjectSettingsMenuItemProps {
|
||||
project: Project
|
||||
}
|
||||
|
||||
const ProjectSettingsMenuItem = ({ project }: ProjectSettingsMenuItemProps) => {
|
||||
const router = useRouter()
|
||||
|
||||
// [Joshen] Links need to be updated once we start implementing these
|
||||
const projectSettings = [
|
||||
{ label: 'General', pathname: `/project/[ref]/settings/general` },
|
||||
{ label: 'Infrastructure', pathname: `/project/[ref]/settings/infrastructure` },
|
||||
{ label: 'Add Ons', pathname: `/project/[ref]/settings/addons` },
|
||||
]
|
||||
|
||||
return (
|
||||
<AccordionItem_Shadcn_ value={project.ref} className="!border-none">
|
||||
<AccordionTrigger_Shadcn_
|
||||
hideIcon
|
||||
className="py-1.5 hover:!no-underline [&[data-state=open]>div>svg]:!rotate-90 [&[data-state=open]>div>p]:text-foreground"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<IconChevronRight
|
||||
className="h-4 w-4 transition-transform duration-200"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
<p className="text-foreground-light text-sm font-normal transition duration-200">
|
||||
{project.name}
|
||||
</p>
|
||||
</div>
|
||||
</AccordionTrigger_Shadcn_>
|
||||
<AccordionContent_Shadcn_>
|
||||
<div className="space-y-2 pl-6 mt-1">
|
||||
{projectSettings.map((link) => {
|
||||
const href = link.pathname.replace('[ref]', project.ref)
|
||||
return (
|
||||
<SettingsMenuItem
|
||||
key={link.label}
|
||||
label={link.label}
|
||||
href={href}
|
||||
isActive={href === router.asPath}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</AccordionContent_Shadcn_>
|
||||
</AccordionItem_Shadcn_>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectSettingsMenuItem
|
||||
@@ -1,37 +0,0 @@
|
||||
import { SupaTable } from 'components/grid'
|
||||
import { formatFilterURLParams, formatSortURLParams } from 'components/grid/SupabaseGrid.utils'
|
||||
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
|
||||
import { useTableRowsPrefetch as _useTableRowsPrefetch } from 'data/table-rows/table-rows-query'
|
||||
import { useUrlState } from 'hooks'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
/**
|
||||
* useTableRowsPrefetchWrapper is a wrapper around the base useTableRowsPrefetch that prefills the sort and filter params
|
||||
*/
|
||||
function useTableRowsPrefetchWrapper() {
|
||||
const [{ sort, filter }] = useUrlState({
|
||||
arrayKeys: ['sort', 'filter'],
|
||||
})
|
||||
const sorts = formatSortURLParams(sort as string[])
|
||||
const filters = formatFilterURLParams(filter as string[])
|
||||
|
||||
const { project } = useProjectContext()
|
||||
const prefetch = _useTableRowsPrefetch()
|
||||
|
||||
return useCallback(
|
||||
(table: SupaTable) =>
|
||||
prefetch({
|
||||
queryKey: [table.schema, table.name],
|
||||
projectRef: project?.ref,
|
||||
connectionString: project?.connectionString,
|
||||
table,
|
||||
sorts,
|
||||
filters,
|
||||
page: 1,
|
||||
limit: 100,
|
||||
}),
|
||||
[project, sorts, filters]
|
||||
)
|
||||
}
|
||||
|
||||
export default useTableRowsPrefetchWrapper
|
||||
@@ -1,63 +0,0 @@
|
||||
import React, { forwardRef } from 'react'
|
||||
|
||||
const FormField = forwardRef(
|
||||
(
|
||||
{
|
||||
id,
|
||||
label,
|
||||
type,
|
||||
description,
|
||||
placeholder,
|
||||
errorMessage,
|
||||
wrapperClasses,
|
||||
children,
|
||||
value,
|
||||
onChange,
|
||||
checked,
|
||||
choices,
|
||||
autoFocus,
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
let options =
|
||||
type === 'select'
|
||||
? Object.keys(choices).map((choice) => {
|
||||
return (
|
||||
<option key={choices[choice]} value={choices[choice]}>
|
||||
{choices[choice]}
|
||||
</option>
|
||||
)
|
||||
})
|
||||
: null
|
||||
|
||||
return (
|
||||
<div className={`form-group ${wrapperClasses ? wrapperClasses : ''}`}>
|
||||
<label htmlFor={id}>{label}</label>
|
||||
{children ? (
|
||||
<div className="form-control inline-block p-3">{children}</div>
|
||||
) : type === 'select' ? (
|
||||
<select id={id} onChange={onChange} defaultValue={value} className="form-control">
|
||||
{options}
|
||||
</select>
|
||||
) : (
|
||||
<input
|
||||
id={id}
|
||||
name={id}
|
||||
className="form-control text-base"
|
||||
ref={ref}
|
||||
type={type}
|
||||
value={value || ''}
|
||||
onChange={onChange}
|
||||
placeholder={placeholder}
|
||||
checked={checked}
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
)}
|
||||
{errorMessage && errorMessage != '' && <p className="form-error">{errorMessage}</p>}
|
||||
{description && <div className="form-text form-help">{description}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default FormField
|
||||
@@ -1,69 +0,0 @@
|
||||
import Ajv from 'ajv'
|
||||
import { PropsWithChildren } from 'react'
|
||||
import { AutoForm } from 'uniforms-bootstrap4'
|
||||
import { JSONSchemaBridge } from 'uniforms-bridge-json-schema'
|
||||
|
||||
interface SchemaFormProps
|
||||
extends PropsWithChildren<{
|
||||
schema: any
|
||||
model: any
|
||||
disabled: boolean
|
||||
formRef: any
|
||||
onSubmit: any
|
||||
onChangeModel: any
|
||||
}> {}
|
||||
|
||||
const SchemaForm = ({
|
||||
schema,
|
||||
model,
|
||||
disabled = false,
|
||||
children,
|
||||
formRef,
|
||||
onSubmit,
|
||||
onChangeModel = () => {},
|
||||
}: SchemaFormProps) => {
|
||||
const validatedSchema = new JSONSchemaBridge(schema, createValidator(schema))
|
||||
return (
|
||||
<AutoForm
|
||||
disabled={disabled}
|
||||
onChangeModel={onChangeModel}
|
||||
ref={formRef}
|
||||
schema={validatedSchema}
|
||||
onSubmit={onSubmit}
|
||||
submitField={() => <></>}
|
||||
model={model}
|
||||
>
|
||||
{children}
|
||||
</AutoForm>
|
||||
)
|
||||
}
|
||||
export default SchemaForm
|
||||
|
||||
let ajv = new Ajv({ strict: false, allErrors: true, useDefaults: true })
|
||||
ajv = ajv.addFormat('absolute-url', '^(http://|https://)')
|
||||
|
||||
const createValidator = (schema: any) => {
|
||||
const validator = ajv.compile(schema)
|
||||
return (model: any) => {
|
||||
let cleansedModel = { ...model }
|
||||
Object.entries(cleansedModel).map(([k, v]) => {
|
||||
const isRequired = schema.required.indexOf(k) != -1
|
||||
// only do nullifyStringIfEmpty if it's a required string property
|
||||
if (typeof v === 'string' && isRequired) cleansedModel[k] = nullifyStringIfEmpty(v)
|
||||
else cleansedModel[k] = v
|
||||
})
|
||||
validator(cleansedModel)
|
||||
if (validator.errors && validator.errors.length) {
|
||||
return { details: validator.errors }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON Schema doesn't support validation for empty strings.
|
||||
* We want to convert all empty strings to NULL to ensure they get validated
|
||||
*/
|
||||
const nullifyStringIfEmpty = (data: any) => {
|
||||
if (data.trim() === '') return null
|
||||
else return data
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import { Button } from 'ui'
|
||||
import SchemaForm from './SchemaForm'
|
||||
|
||||
export default function SchemaFormPanel({
|
||||
schema,
|
||||
title,
|
||||
model,
|
||||
children,
|
||||
onChangeModel = () => {},
|
||||
onReset = () => {},
|
||||
onSubmit,
|
||||
loading,
|
||||
submitLabel = 'Save',
|
||||
cancelLabel = 'Cancel',
|
||||
message = '',
|
||||
disabled = false,
|
||||
disabledMessage = '',
|
||||
}: any) {
|
||||
let formRef: any
|
||||
const [submitButtonLoading, setSubmitButtonLoading] = useState(false)
|
||||
const [hasChanged, setHasChanged] = useState(false)
|
||||
const isLoading = loading !== undefined ? loading : submitButtonLoading
|
||||
|
||||
function onClickCancel() {
|
||||
formRef.reset()
|
||||
setSubmitButtonLoading(false)
|
||||
setHasChanged(false)
|
||||
if (onReset) onReset()
|
||||
}
|
||||
|
||||
const onClickSubmit = () => {
|
||||
formRef
|
||||
.submit()
|
||||
.then(() => {
|
||||
setSubmitButtonLoading(true)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('Error on submitting', error)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="section-block mb-8">
|
||||
<div
|
||||
className="
|
||||
flex h-12
|
||||
items-center overflow-hidden
|
||||
border-b px-6
|
||||
border-overlay bg-surface-100
|
||||
"
|
||||
>
|
||||
<div className="flex-1 text-left">
|
||||
<h6>{title || ''}</h6>
|
||||
</div>
|
||||
{disabled && disabledMessage ? (
|
||||
<p className="text-sm text-foreground-light">{disabledMessage}</p>
|
||||
) : (
|
||||
<div
|
||||
className={`flex transition duration-150 ${
|
||||
hasChanged ? 'opacity-100' : 'cursor-default opacity-0'
|
||||
}`}
|
||||
>
|
||||
<Button onClick={onClickCancel} type="default" disabled={!hasChanged || isLoading}>
|
||||
{cancelLabel || 'Cancel'}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onClickSubmit}
|
||||
loading={isLoading}
|
||||
disabled={disabled || !hasChanged || isLoading}
|
||||
type="primary"
|
||||
className="ml-2 hover:border-green-500"
|
||||
>
|
||||
{submitLabel || 'Save'}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<span className="text-sm text-foreground-lighter">{message}</span>
|
||||
</div>
|
||||
|
||||
<div className="Form section-block--body px-6 py-3">
|
||||
<SchemaForm
|
||||
disabled={disabled}
|
||||
onChangeModel={(model: any) => {
|
||||
setHasChanged(true)
|
||||
if (onChangeModel) onChangeModel(model)
|
||||
}}
|
||||
formRef={(ref: any) => (formRef = ref)}
|
||||
schema={schema}
|
||||
model={model}
|
||||
onSubmit={async (args: any) => {
|
||||
onSubmit(args)
|
||||
.then(() => {
|
||||
setSubmitButtonLoading(false)
|
||||
setHasChanged(false)
|
||||
})
|
||||
.catch(() => setSubmitButtonLoading(false))
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SchemaForm>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { IconEye, IconEyeOff } from 'ui'
|
||||
import { connectField, filterDOMProps } from 'uniforms'
|
||||
|
||||
const SecretField: React.FC = (props: any) => {
|
||||
const { disabled, id, inputRef, label, name, onChange, value, help, error, errorMessage } = props
|
||||
const [text, setText] = React.useState(value)
|
||||
const [visible, setVisible] = React.useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
setText(value)
|
||||
}, [value])
|
||||
|
||||
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const newValue = e.target.value
|
||||
setText(newValue)
|
||||
onChange(newValue)
|
||||
}
|
||||
|
||||
function onToggleVisible() {
|
||||
setVisible(!visible)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="form-group" {...filterDOMProps(props)}>
|
||||
{label && <label htmlFor={id}>{label}</label>}
|
||||
<div className="form-control flex flex-col">
|
||||
<div className="inline-flex items-center">
|
||||
<input
|
||||
disabled={disabled}
|
||||
id={id}
|
||||
name={name}
|
||||
ref={inputRef}
|
||||
value={text}
|
||||
onChange={handleChange}
|
||||
type={visible ? 'text' : 'password'}
|
||||
/>
|
||||
<div className="px-2" onClick={onToggleVisible}>
|
||||
{visible ? (
|
||||
<IconEye className="text-foreground-lighter" />
|
||||
) : (
|
||||
<IconEyeOff className="text-foreground-lighter" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{error && <span className="form-text text-muted">{errorMessage ?? error.message}</span>}
|
||||
{help && <span className="form-text text-muted">{help}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connectField(SecretField, { kind: 'leaf' })
|
||||
@@ -1,42 +0,0 @@
|
||||
const sizes = {
|
||||
md: {
|
||||
slider: 'h-5 w-5',
|
||||
toggleOn: 'translate-x-5',
|
||||
toggleOff: 'translate-x-0',
|
||||
background: 'h-6 w-11 border-2',
|
||||
},
|
||||
sm: {
|
||||
slider: 'h-4 w-4',
|
||||
toggleOn: 'translate-x-3',
|
||||
toggleOff: 'translate-x-0',
|
||||
background: 'h-5 w-9 border-2',
|
||||
},
|
||||
}
|
||||
|
||||
export default function Toggle({
|
||||
isOn = true,
|
||||
size = 'md',
|
||||
onToggle = (value) => {},
|
||||
isDisabled = false,
|
||||
}) {
|
||||
const toggleSizes = sizes[size]
|
||||
return (
|
||||
<span
|
||||
role="checkbox"
|
||||
aria-checked="false"
|
||||
onClick={!isDisabled ? () => onToggle(!isOn) : () => {}}
|
||||
className={`${isOn ? 'bg-green-500' : 'bg-gray-200'} ${toggleSizes.background} ${
|
||||
isDisabled ? 'cursor-not-allowed' : 'cursor-pointer'
|
||||
} relative inline-block flex-shrink-0 border-transparent rounded-full transition-colors ease-in-out duration-200 focus:outline-none focus:ring `}
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={`${isOn ? toggleSizes.toggleOn : toggleSizes.toggleOff} ${
|
||||
isDisabled ? 'cursor-not-allowed bg-white' : 'cursor-pointer bg-white'
|
||||
} ${
|
||||
toggleSizes.slider
|
||||
} inline-block rounded-full shadow transform transition ease-in-out duration-200`}
|
||||
></span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { connectField, filterDOMProps } from 'uniforms'
|
||||
import { Toggle } from 'ui'
|
||||
|
||||
function ToggleField({
|
||||
disabled,
|
||||
id,
|
||||
inputRef,
|
||||
label,
|
||||
name,
|
||||
onChange,
|
||||
value,
|
||||
help,
|
||||
addOns,
|
||||
...props
|
||||
}) {
|
||||
const [enabled, setEnable] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
setEnable(value)
|
||||
}, [value])
|
||||
|
||||
function onToggle() {
|
||||
const newValue = !enabled
|
||||
setEnable(newValue)
|
||||
onChange(newValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="form-group items-center" {...filterDOMProps(props)}>
|
||||
<input
|
||||
disabled={disabled}
|
||||
id={id}
|
||||
name={name}
|
||||
ref={inputRef}
|
||||
type="checkbox"
|
||||
style={{ display: 'none' }}
|
||||
/>
|
||||
|
||||
{label && <label htmlFor={id}>{label}</label>}
|
||||
<div className="form-control flex items-center">
|
||||
<Toggle onChange={disabled ? undefined : onToggle} checked={enabled} />
|
||||
{addOns && addOns}
|
||||
</div>
|
||||
{help && <span className="form-text text-muted">{help}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connectField(ToggleField, { kind: 'leaf' })
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Button, IconArrowLeft } from 'ui'
|
||||
|
||||
export function BackButton({ onClick }: { onClick: () => void }) {
|
||||
return (
|
||||
<div className="-ml-2 2xl:absolute 2xl:top-[2px] 2xl:left-0">
|
||||
<Button type="text" icon={<IconArrowLeft />} onClick={onClick}>
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BackButton
|
||||
@@ -1,34 +0,0 @@
|
||||
import Link from 'next/link'
|
||||
import { Button, IconAlertCircle } from 'ui'
|
||||
|
||||
export interface ClientLoadingErrorProps {
|
||||
projectRef: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const ClientLoadingError = ({
|
||||
projectRef,
|
||||
description = 'An error has occurred',
|
||||
}: ClientLoadingErrorProps) => {
|
||||
return (
|
||||
<div className="px-6 py-4 bg-surface-200 border border-overlay rounded flex justify-between items-center">
|
||||
<div className="flex space-x-4">
|
||||
<IconAlertCircle strokeWidth={1.5} className="text-foreground-light" />
|
||||
<div className="space-y-1">
|
||||
<p className="text-sm text-foreground">{description}</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Try refreshing your browser. However, if this issue persists, please reach out to us via
|
||||
support.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button asChild>
|
||||
<Link href={`/support/new?ref=${projectRef}`} target="_blank" rel="noreferrer">
|
||||
Contact support
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ClientLoadingError
|
||||
@@ -1,19 +0,0 @@
|
||||
export default function DividerSlash() {
|
||||
return (
|
||||
<span className="text-foreground-lighter">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="14"
|
||||
height="14"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
shapeRendering="geometricPrecision"
|
||||
>
|
||||
<path d="M16 3.549L7.12 20.600"></path>
|
||||
</svg>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { IconAlertCircle } from 'ui'
|
||||
|
||||
const WarningBanner = ({ title, description }: { title: string; description?: string }) => {
|
||||
return (
|
||||
<div className="rounded bg-warning-200 px-6 py-3">
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="mt-1 text-warning">
|
||||
<IconAlertCircle size={14} strokeWidth={2} />
|
||||
</div>
|
||||
<div className="flex flex-col items-start gap-x-3 xl:flex-row xl:items-center">
|
||||
<h2 className="text-sm text-foreground">{title}</h2>
|
||||
{description && <p className="text-xs text-warning">{description}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default WarningBanner
|
||||
@@ -1,124 +0,0 @@
|
||||
const Base64 = {
|
||||
// private property
|
||||
_keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
||||
|
||||
// public method for encoding
|
||||
encode: function (input: string) {
|
||||
var output = ''
|
||||
var chr1, chr2, chr3, enc1, enc2, enc3, enc4
|
||||
var i = 0
|
||||
|
||||
input = Base64._utf8_encode(input)
|
||||
|
||||
while (i < input.length) {
|
||||
chr1 = input.charCodeAt(i++)
|
||||
chr2 = input.charCodeAt(i++)
|
||||
chr3 = input.charCodeAt(i++)
|
||||
|
||||
enc1 = chr1 >> 2
|
||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4)
|
||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6)
|
||||
enc4 = chr3 & 63
|
||||
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64
|
||||
}
|
||||
|
||||
output =
|
||||
output +
|
||||
Base64._keyStr.charAt(enc1) +
|
||||
Base64._keyStr.charAt(enc2) +
|
||||
Base64._keyStr.charAt(enc3) +
|
||||
Base64._keyStr.charAt(enc4)
|
||||
}
|
||||
|
||||
return output
|
||||
},
|
||||
|
||||
// public method for decoding
|
||||
decode: function (input: string) {
|
||||
var output = ''
|
||||
var chr1, chr2, chr3
|
||||
var enc1, enc2, enc3, enc4
|
||||
var i = 0
|
||||
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '')
|
||||
|
||||
while (i < input.length) {
|
||||
enc1 = Base64._keyStr.indexOf(input.charAt(i++))
|
||||
enc2 = Base64._keyStr.indexOf(input.charAt(i++))
|
||||
enc3 = Base64._keyStr.indexOf(input.charAt(i++))
|
||||
enc4 = Base64._keyStr.indexOf(input.charAt(i++))
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4)
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2)
|
||||
chr3 = ((enc3 & 3) << 6) | enc4
|
||||
|
||||
output = output + String.fromCharCode(chr1)
|
||||
|
||||
if (enc3 != 64) {
|
||||
output = output + String.fromCharCode(chr2)
|
||||
}
|
||||
if (enc4 != 64) {
|
||||
output = output + String.fromCharCode(chr3)
|
||||
}
|
||||
}
|
||||
|
||||
output = Base64._utf8_decode(output)
|
||||
|
||||
return output
|
||||
},
|
||||
|
||||
// private method for UTF-8 encoding
|
||||
_utf8_encode: function (string: string) {
|
||||
string = string.replace(/\r\n/g, '\n')
|
||||
var utftext = ''
|
||||
|
||||
for (var n = 0; n < string.length; n++) {
|
||||
var c = string.charCodeAt(n)
|
||||
|
||||
if (c < 128) {
|
||||
utftext += String.fromCharCode(c)
|
||||
} else if (c > 127 && c < 2048) {
|
||||
utftext += String.fromCharCode((c >> 6) | 192)
|
||||
utftext += String.fromCharCode((c & 63) | 128)
|
||||
} else {
|
||||
utftext += String.fromCharCode((c >> 12) | 224)
|
||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128)
|
||||
utftext += String.fromCharCode((c & 63) | 128)
|
||||
}
|
||||
}
|
||||
return utftext
|
||||
},
|
||||
|
||||
// private method for UTF-8 decoding
|
||||
_utf8_decode: function (utftext: string) {
|
||||
var string = ''
|
||||
var i = 0
|
||||
var c = 0,
|
||||
c1 = 0,
|
||||
c2 = 0
|
||||
|
||||
while (i < utftext.length) {
|
||||
c = utftext.charCodeAt(i)
|
||||
|
||||
if (c < 128) {
|
||||
string += String.fromCharCode(c)
|
||||
i++
|
||||
} else if (c > 191 && c < 224) {
|
||||
c1 = utftext.charCodeAt(i + 1)
|
||||
string += String.fromCharCode(((c & 31) << 6) | (c1 & 63))
|
||||
i += 2
|
||||
} else {
|
||||
c1 = utftext.charCodeAt(i + 1)
|
||||
c2 = utftext.charCodeAt(i + 2)
|
||||
string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63))
|
||||
i += 3
|
||||
}
|
||||
}
|
||||
return string
|
||||
},
|
||||
}
|
||||
export default Base64
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
STORAGE_ROW_TYPES,
|
||||
STORAGE_SORT_BY,
|
||||
STORAGE_VIEWS,
|
||||
} from 'components/to-be-cleaned/Storage/Storage.constants.ts'
|
||||
} from 'components/to-be-cleaned/Storage/Storage.constants'
|
||||
import { useStore } from 'hooks'
|
||||
import { delete_, post } from 'lib/common/fetch'
|
||||
import { API_URL, IS_PLATFORM } from 'lib/constants'
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"@zip.js/zip.js": "^2.7.29",
|
||||
"ai": "^2.2.26",
|
||||
"ajv": "^8.6.3",
|
||||
"awesome-debounce-promise": "^2.1.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"clsx": "^1.2.1",
|
||||
@@ -100,8 +99,6 @@
|
||||
"sql-formatter": "^12.2.0",
|
||||
"sqlstring": "^2.3.2",
|
||||
"ui": "*",
|
||||
"uniforms-bootstrap4": "^3.6.2",
|
||||
"uniforms-bridge-json-schema": "^3.6.2",
|
||||
"uuid": "^9.0.1",
|
||||
"valtio": "^1.11.2",
|
||||
"yup": "^0.32.11",
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "inserted_at", "updated_at", "api_key", "key_name", "project_id"],
|
||||
"properties": {
|
||||
"api_key": {
|
||||
"title": "Api Key",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"key_name": {
|
||||
"title": "Key Name",
|
||||
"type": "string"
|
||||
},
|
||||
"project_id": {
|
||||
"title": "Project Id",
|
||||
"type": "number"
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "inserted_at", "updated_at", "name"],
|
||||
"properties": {
|
||||
"config_schema": {
|
||||
"title": "Config Schema",
|
||||
"type": "object"
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,616 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"SITE_URL",
|
||||
"DISABLE_SIGNUP",
|
||||
"SECURITY_MANUAL_LINKING_ENABLED",
|
||||
"JWT_EXP",
|
||||
"JWT_AUD",
|
||||
"JWT_DEFAULT_GROUP_NAME",
|
||||
"SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION",
|
||||
"EXTERNAL_EMAIL_ENABLED",
|
||||
"EXTERNAL_PHONE_ENABLED",
|
||||
"EXTERNAL_APPLE_ENABLED",
|
||||
"EXTERNAL_AZURE_ENABLED",
|
||||
"EXTERNAL_BITBUCKET_ENABLED",
|
||||
"EXTERNAL_DISCORD_ENABLED",
|
||||
"EXTERNAL_FACEBOOK_ENABLED",
|
||||
"EXTERNAL_GITHUB_ENABLED",
|
||||
"EXTERNAL_GITLAB_ENABLED",
|
||||
"EXTERNAL_GOOGLE_ENABLED",
|
||||
"EXTERNAL_KAKAO_ENABLED",
|
||||
"EXTERNAL_KEYCLOAK_ENABLED",
|
||||
"EXTERNAL_LINKEDIN_ENABLED",
|
||||
"EXTERNAL_NOTION_ENABLED",
|
||||
"EXTERNAL_TWITCH_ENABLED",
|
||||
"EXTERNAL_TWITTER_ENABLED",
|
||||
"EXTERNAL_SLACK_ENABLED",
|
||||
"EXTERNAL_SPOTIFY_ENABLED",
|
||||
"EXTERNAL_WORKOS_ENABLED",
|
||||
"EXTERNAL_ZOOM_ENABLED",
|
||||
"SMS_AUTOCONFIRM",
|
||||
"SMS_MAX_FREQUENCY",
|
||||
"SMS_OTP_EXP",
|
||||
"SMS_OTP_LENGTH",
|
||||
"SMS_PROVIDER",
|
||||
"SMS_TEMPLATE",
|
||||
"MAILER_AUTOCONFIRM",
|
||||
"MAILER_OTP_EXP",
|
||||
"MAILER_URLPATHS_INVITE",
|
||||
"MAILER_URLPATHS_CONFIRMATION",
|
||||
"MAILER_URLPATHS_RECOVERY",
|
||||
"MAILER_URLPATHS_EMAIL_CHANGE",
|
||||
"MAILER_SUBJECTS_INVITE",
|
||||
"MAILER_SUBJECTS_CONFIRMATION",
|
||||
"MAILER_SUBJECTS_RECOVERY",
|
||||
"MAILER_SUBJECTS_MAGIC_LINK",
|
||||
"MAILER_SUBJECTS_EMAIL_CHANGE",
|
||||
"MAILER_TEMPLATES_INVITE_CONTENT",
|
||||
"MAILER_TEMPLATES_CONFIRMATION_CONTENT",
|
||||
"MAILER_TEMPLATES_RECOVERY_CONTENT",
|
||||
"MAILER_TEMPLATES_MAGIC_LINK_CONTENT",
|
||||
"MAILER_TEMPLATES_EMAIL_CHANGE_CONTENT"
|
||||
],
|
||||
"properties": {
|
||||
"SITE_URL": {
|
||||
"title": "Site URL",
|
||||
"type": "string",
|
||||
"help": "The base URL of your website. Used as an allow-list for redirects and for constructing URLs used in emails."
|
||||
},
|
||||
"URI_ALLOW_LIST": {
|
||||
"title": "Additional redirect URLs",
|
||||
"type": "string",
|
||||
"help": "A comma separated list of URLs that auth providers are permitted to redirect to post authentication. Wildcards allowed (e.g. https://*.domain.com)"
|
||||
},
|
||||
"DISABLE_SIGNUP": {
|
||||
"title": "Disable signup",
|
||||
"type": "boolean",
|
||||
"help": "Allow/disallow new user signups for your project."
|
||||
},
|
||||
"SECURITY_MANUAL_LINKING_ENABLED": {
|
||||
"title": "Enable Manual Linking",
|
||||
"type": "boolean",
|
||||
"help": "Enable manual linking APIs for your project"
|
||||
},
|
||||
"EXTERNAL_EMAIL_ENABLED": {
|
||||
"title": "Enable email signup",
|
||||
"type": "boolean",
|
||||
"help": "Allow/disallow new user signups via email to your project."
|
||||
},
|
||||
"EXTERNAL_PHONE_ENABLED": {
|
||||
"title": "Enable phone signup",
|
||||
"type": "boolean",
|
||||
"help": "Allow/disallow new user signups via phone to your project."
|
||||
},
|
||||
"JWT_EXP": {
|
||||
"title": "JWT expiry",
|
||||
"type": "integer",
|
||||
"help": "How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 seconds (one week).",
|
||||
"minimum": 1,
|
||||
"maximum": 604800,
|
||||
"multipleof": 1
|
||||
},
|
||||
"JWT_AUD": {
|
||||
"title": "JWT audience",
|
||||
"type": "string"
|
||||
},
|
||||
"JWT_DEFAULT_GROUP_NAME": {
|
||||
"title": "Default user group",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_APPLE_ENABLED": {
|
||||
"title": "Apple enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_APPLE_CLIENT_ID": {
|
||||
"title": "Apple client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_APPLE_SECRET": {
|
||||
"title": "Apple secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_AZURE_ENABLED": {
|
||||
"title": "Azure enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_AZURE_CLIENT_ID": {
|
||||
"title": "Azure client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_AZURE_SECRET": {
|
||||
"title": "Azure secret",
|
||||
"type": "string",
|
||||
"help": "Enter the data from Value, not the Secret ID."
|
||||
},
|
||||
"EXTERNAL_AZURE_URL": {
|
||||
"title": "Azure tenant URL",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_BITBUCKET_ENABLED": {
|
||||
"title": "Bitbucket enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_BITBUCKET_CLIENT_ID": {
|
||||
"title": "Bitbucket client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_BITBUCKET_SECRET": {
|
||||
"title": "Bitbucket secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_DISCORD_ENABLED": {
|
||||
"title": "Discord enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_DISCORD_CLIENT_ID": {
|
||||
"title": "Discord client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_DISCORD_SECRET": {
|
||||
"title": "Discord secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_FACEBOOK_ENABLED": {
|
||||
"title": "Facebook enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_FACEBOOK_CLIENT_ID": {
|
||||
"title": "Facebook client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_FACEBOOK_SECRET": {
|
||||
"title": "Facebook secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_FIGMA_ENABLED": {
|
||||
"title": "Figma enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_FIGMA_CLIENT_ID": {
|
||||
"title": "Figma client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_FIGMA_SECRET": {
|
||||
"title": "Figma secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GITHUB_ENABLED": {
|
||||
"title": "GitHub enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_GITHUB_CLIENT_ID": {
|
||||
"title": "GitHub client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GITHUB_SECRET": {
|
||||
"title": "GitHub secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GITLAB_ENABLED": {
|
||||
"title": "GitLab enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_GITLAB_CLIENT_ID": {
|
||||
"title": "GitLab client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GITLAB_SECRET": {
|
||||
"title": "Gitlab secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GITLAB_URL": {
|
||||
"title": "The base URL used for constructing the URLs to request authorization and access tokens.",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GOOGLE_ENABLED": {
|
||||
"title": "Google enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_GOOGLE_CLIENT_ID": {
|
||||
"title": "Google client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_GOOGLE_SECRET": {
|
||||
"title": "Google secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_KAKAO_ENABLED": {
|
||||
"title": "Kakao enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_KAKAO_CLIENT_ID": {
|
||||
"title": "Kakao client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_KAKAO_SECRET": {
|
||||
"title": "Kakao secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_KEYCLOAK_ENABLED": {
|
||||
"title": "Keycloak enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_KEYCLOAK_CLIENT_ID": {
|
||||
"title": "Keycloak client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_KEYCLOAK_SECRET": {
|
||||
"title": "Keycloak secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_KEYCLOAK_URL": {
|
||||
"title": "Keycloak URL",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_LINKEDIN_ENABLED": {
|
||||
"title": "Linkedin enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_LINKEDIN_CLIENT_ID": {
|
||||
"title": "Linkedin client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_LINKEDIN_SECRET": {
|
||||
"title": "Linkedin secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_LINKEDIN_OIDC_ENABLED": {
|
||||
"title": "LinkedIn enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_LINKEDIN_OIDC_CLIENT_ID": {
|
||||
"title": "LinkedIn client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_LINKEDIN_OIDC_SECRET": {
|
||||
"title": "LinkedIn secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_NOTION_ENABLED": {
|
||||
"title": "Notion enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_NOTION_CLIENT_ID": {
|
||||
"title": "Notion client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_NOTION_SECRET": {
|
||||
"title": "Notion secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_TWITCH_ENABLED": {
|
||||
"title": "Twitch enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_TWITCH_CLIENT_ID": {
|
||||
"title": "Twitch client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_TWITCH_SECRET": {
|
||||
"title": "Twitch secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_TWITTER_ENABLED": {
|
||||
"title": "Twitter enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_TWITTER_CLIENT_ID": {
|
||||
"title": "Twitter client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_TWITTER_SECRET": {
|
||||
"title": "Twitter secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_SLACK_ENABLED": {
|
||||
"title": "Slack enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_SLACK_CLIENT_ID": {
|
||||
"title": "Slack client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_SLACK_SECRET": {
|
||||
"title": "Slack secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_SPOTIFY_ENABLED": {
|
||||
"title": "Spotify enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_SPOTIFY_CLIENT_ID": {
|
||||
"title": "Spotify client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_SPOTIFY_SECRET": {
|
||||
"title": "Spotify secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_WORKOS_ENABLED": {
|
||||
"title": "WorkOS enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_WORKOS_CLIENT_ID": {
|
||||
"title": "WorkOS client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_WORKOS_SECRET": {
|
||||
"title": "WorkOS secret",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_WORKOS_URL": {
|
||||
"title": "WorkOS URL",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_ZOOM_ENABLED": {
|
||||
"title": "Zoom enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"EXTERNAL_ZOOM_CLIENT_ID": {
|
||||
"title": "Zoom client ID",
|
||||
"type": "string"
|
||||
},
|
||||
"EXTERNAL_ZOOM_SECRET": {
|
||||
"title": "Zoom secret",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_ADMIN_EMAIL": {
|
||||
"title": "SMTP admin email",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_HOST": {
|
||||
"title": "SMTP host",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_PORT": {
|
||||
"title": "SMTP port",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_USER": {
|
||||
"title": "SMTP user",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_PASS": {
|
||||
"title": "SMTP password",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_PASS_ENCRYPTED": {
|
||||
"title": "SMTP password",
|
||||
"type": "string"
|
||||
},
|
||||
"SMTP_SENDER_NAME": {
|
||||
"title": "SMTP sender name",
|
||||
"type": "string"
|
||||
},
|
||||
"RATE_LIMIT_EMAIL_SENT": {
|
||||
"title": "Rate limit",
|
||||
"type": "number",
|
||||
"help": "Maximum number of emails sent per hour (Default: 30, Max: 32,767)",
|
||||
"minimum": 1,
|
||||
"maximum": 32767,
|
||||
"multipleof": 1
|
||||
},
|
||||
"RATE_LIMIT_SMS_SENT": {
|
||||
"title": "Rate limit",
|
||||
"type": "number",
|
||||
"help": "Maximum number of SMS messages sent per hour (Default: 30, Max: 32,767)",
|
||||
"minimum": 1,
|
||||
"maximum": 32767,
|
||||
"multipleof": 1
|
||||
},
|
||||
"MAILER_SECURE_EMAIL_CHANGE_ENABLED": {
|
||||
"title": "Double confirm email changes",
|
||||
"type": "boolean",
|
||||
"help": "If enabled, a user will be required to confirm any email change on both the old, and new email addresses. If disabled, only the new email is required to confirm"
|
||||
},
|
||||
"MAILER_AUTOCONFIRM": {
|
||||
"title": "Enable email confirmations",
|
||||
"type": "boolean",
|
||||
"help": "If enabled, users need to confirm their email address before signing in."
|
||||
},
|
||||
"MAILER_URLPATHS_INVITE": {
|
||||
"title": "Confirmation URL",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_URLPATHS_CONFIRMATION": {
|
||||
"title": "Path",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_URLPATHS_RECOVERY": {
|
||||
"title": "Confirmation URL",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_URLPATHS_EMAIL_CHANGE": {
|
||||
"title": "Confirmation URL",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_SUBJECTS_INVITE": {
|
||||
"title": "Subject",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_OTP_EXP": {
|
||||
"title": "Mailer Otp Expiration",
|
||||
"type": "integer",
|
||||
"help": "Duration before an email otp / link expires."
|
||||
},
|
||||
|
||||
"MAILER_SUBJECTS_CONFIRMATION": {
|
||||
"title": "Subject",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_SUBJECTS_MAGIC_LINK": {
|
||||
"title": "Subject",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_SUBJECTS_RECOVERY": {
|
||||
"title": "Subject",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_SUBJECTS_EMAIL_CHANGE": {
|
||||
"title": "Subject",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_INVITE": {
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_INVITE_CONTENT": {
|
||||
"title": "Body",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_CONFIRMATION": {
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_CONFIRMATION_CONTENT": {
|
||||
"title": "Body",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_RECOVERY": {
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_MAGIC_LINK": {
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_RECOVERY_CONTENT": {
|
||||
"title": "Body",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_MAGIC_LINK_CONTENT": {
|
||||
"title": "Body",
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_EMAIL_CHANGE": {
|
||||
"type": "string"
|
||||
},
|
||||
"MAILER_TEMPLATES_EMAIL_CHANGE_CONTENT": {
|
||||
"title": "Body",
|
||||
"type": "string"
|
||||
},
|
||||
"MFA_MAX_ENROLLED_FACTORS": {
|
||||
"title": "Maximum enrolled factors",
|
||||
"type": "integer"
|
||||
},
|
||||
"PASSWORD_MIN_LENGTH": {
|
||||
"title": "Minimum password length",
|
||||
"type": "integer"
|
||||
},
|
||||
"SECURITY_CAPTCHA_ENABLED": {
|
||||
"title": "hCaptcha protection",
|
||||
"type": "boolean",
|
||||
"help": "Enables hCaptcha protection on all auth endpoints."
|
||||
},
|
||||
"SECURITY_CAPTCHA_SECRET": {
|
||||
"title": "hCaptcha sitekey",
|
||||
"type": "string",
|
||||
"help": "Secret (sitekey) used to verify hCaptcha challenges."
|
||||
},
|
||||
"SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION": {
|
||||
"title": "Enable strict password updates",
|
||||
"type": "boolean",
|
||||
"help": "If enabled, users need to reauthenticate via email or phone before updating their passwords."
|
||||
},
|
||||
"SECURITY_REFRESH_TOKEN_REUSE_INTERVAL": {
|
||||
"title": "Reuse Interval",
|
||||
"type": "integer",
|
||||
"help": "Time interval where the same refresh token can be used to request for an access token."
|
||||
},
|
||||
"SMS_AUTOCONFIRM": {
|
||||
"title": "Enable phone confirmations",
|
||||
"type": "boolean",
|
||||
"help": "If enabled, users need to confirm their phone number before signing in."
|
||||
},
|
||||
"SMS_OTP_EXP": {
|
||||
"title": "Sms Otp Expiration",
|
||||
"type": "integer",
|
||||
"help": "Duration before an sms otp expires."
|
||||
},
|
||||
"SMS_OTP_LENGTH": {
|
||||
"title": "Sms Otp Length",
|
||||
"type": "integer",
|
||||
"help": "Number of digits in otp."
|
||||
},
|
||||
"SMS_PROVIDER": {
|
||||
"title": "Sms provider",
|
||||
"type": "string",
|
||||
"options": [
|
||||
{
|
||||
"value": "twilio",
|
||||
"label": "Twilio"
|
||||
},
|
||||
{
|
||||
"value": "messagebird",
|
||||
"label": "Messagebird"
|
||||
},
|
||||
{
|
||||
"value": "vonage",
|
||||
"label": "Vonage"
|
||||
},
|
||||
{
|
||||
"value": "textlocal",
|
||||
"label": "Textlocal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SMS_TEXTLOCAL_API_KEY": {
|
||||
"title": "Textlocal API key",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_TEXTLOCAL_SENDER": {
|
||||
"title": "Textlocal sender",
|
||||
"type": "string",
|
||||
"help": "Textlocal sender phone number"
|
||||
},
|
||||
"SMS_TWILIO_ACCOUNT_SID": {
|
||||
"title": "Twilio account SID",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_TWILIO_AUTH_TOKEN": {
|
||||
"title": "Twilio auth token",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_TWILIO_MESSAGE_SERVICE_SID": {
|
||||
"title": "Twilio message service SID",
|
||||
"type": "string",
|
||||
"help": "Twilio message service SID or twilio phone number"
|
||||
},
|
||||
"SMS_TWILIO_VERIFY_ACCOUNT_SID": {
|
||||
"title": "Twilio account SID",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_TWILIO_VERIFY_AUTH_TOKEN": {
|
||||
"title": "Twilio Verify auth token",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_TWILIO_VERIFY_MESSAGE_SERVICE_SID": {
|
||||
"title": "Twilio Verify service SID",
|
||||
"type": "string",
|
||||
"help": "Twilio Verify service SID"
|
||||
},
|
||||
"SMS_MESSAGEBIRD_ACCESS_KEY": {
|
||||
"title": "Messagebird access key",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_MESSAGEBIRD_ORIGINATOR": {
|
||||
"title": "Messagebird originator",
|
||||
"type": "string",
|
||||
"help": "Messagebird sender name or phone number"
|
||||
},
|
||||
"SMS_VONAGE_API_KEY": {
|
||||
"title": "Vonage API key",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_VONAGE_API_SECRET": {
|
||||
"title": "Vonage API secret",
|
||||
"type": "string"
|
||||
},
|
||||
"SMS_VONAGE_FROM": {
|
||||
"title": "Vonage sender",
|
||||
"type": "string",
|
||||
"help": "Vonage sender phone number"
|
||||
},
|
||||
"SMS_TEMPLATE": {
|
||||
"title": "Body",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import api_keys from './api_keys'
|
||||
import apps from './apps'
|
||||
import infrastructure from './infrastructure'
|
||||
import members from './members'
|
||||
import organizations from './organizations'
|
||||
import products from './products'
|
||||
import projects from './projects'
|
||||
import schema_migrations from './schema_migrations'
|
||||
import services from './services'
|
||||
import users from './users'
|
||||
import authConfig from './auth_gotrue_config'
|
||||
|
||||
export {
|
||||
api_keys,
|
||||
apps,
|
||||
infrastructure,
|
||||
members,
|
||||
organizations,
|
||||
products,
|
||||
projects,
|
||||
schema_migrations,
|
||||
services,
|
||||
users,
|
||||
authConfig,
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"inserted_at",
|
||||
"updated_at",
|
||||
"infrastructure_type",
|
||||
"status",
|
||||
"provider_reference",
|
||||
"provider"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"infrastructure_type": {
|
||||
"title": "Infrastructure Type",
|
||||
"type": "string",
|
||||
"enum": ["DATABASE", "WEB_SERVER"]
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"ipv4_address": {
|
||||
"title": "Ipv4 Address",
|
||||
"type": "string"
|
||||
},
|
||||
"provider": {
|
||||
"title": "Provider",
|
||||
"type": "string"
|
||||
},
|
||||
"provider_reference": {
|
||||
"title": "Provider Reference",
|
||||
"type": "string"
|
||||
},
|
||||
"service_id": {
|
||||
"title": "Service Id",
|
||||
"type": "number"
|
||||
},
|
||||
"status": {
|
||||
"title": "Status",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"INACTIVE",
|
||||
"ACTIVE_HEALTHY",
|
||||
"ACTIVE_UNHEALTHY",
|
||||
"COMING_UP",
|
||||
"UNKNOWN",
|
||||
"GOING_DOWN",
|
||||
"REMOVED"
|
||||
]
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"title": "Url",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "is_owner"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"is_owner": {
|
||||
"title": "Is Owner",
|
||||
"type": "boolean"
|
||||
},
|
||||
"organization_id": {
|
||||
"title": "Organization Id",
|
||||
"type": "number"
|
||||
},
|
||||
"user_id": {
|
||||
"title": "User Id",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "inserted_at", "updated_at", "slug", "name"],
|
||||
"properties": {
|
||||
"badge": {
|
||||
"title": "Badge",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_address_line_1": {
|
||||
"title": "Billing Address Line 1",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_address_line_2": {
|
||||
"title": "Billing Address Line 2",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_city": {
|
||||
"title": "Billing City",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_country": {
|
||||
"title": "Billing Country",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_email": {
|
||||
"title": "Billing Email",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_expiry": {
|
||||
"title": "Billing Expiry",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_phone": {
|
||||
"title": "Billing Phone",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_postal_code": {
|
||||
"title": "Billing Postal Code",
|
||||
"type": "string"
|
||||
},
|
||||
"billing_state": {
|
||||
"title": "Billing State",
|
||||
"type": "string"
|
||||
},
|
||||
"credit_card_last_four_digits": {
|
||||
"title": "Credit Card Last Four Digits",
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"title": "Phone",
|
||||
"type": "string"
|
||||
},
|
||||
"slug": {
|
||||
"title": "Slug",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_customer_id": {
|
||||
"title": "Stripe Customer Id",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_monthly_subscription_id": {
|
||||
"title": "Stripe Monthly Subscription Id",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_payment_method_id": {
|
||||
"title": "Stripe Payment Method Id",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_yearly_subscription_id": {
|
||||
"title": "Stripe Yearly Subscription Id",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "inserted_at", "updated_at", "name"],
|
||||
"properties": {
|
||||
"feature_rights": {
|
||||
"title": "Feature Rights",
|
||||
"type": "object"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
"product_config": {
|
||||
"title": "Product Config",
|
||||
"type": "string"
|
||||
},
|
||||
"product_type": {
|
||||
"title": "Product Type",
|
||||
"type": "string",
|
||||
"enum": ["API", "CDC"]
|
||||
},
|
||||
"stripe_monthly_plan_id": {
|
||||
"title": "Stripe Monthly Plan Id",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_product_id": {
|
||||
"title": "Stripe Product Id",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_yearly_plan_id": {
|
||||
"title": "Stripe Yearly Plan Id",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"inserted_at",
|
||||
"updated_at",
|
||||
"organization_id",
|
||||
"name",
|
||||
"db_host",
|
||||
"db_name",
|
||||
"db_user",
|
||||
"db_pass",
|
||||
"db_port",
|
||||
"db_ssl",
|
||||
"ref"
|
||||
],
|
||||
"properties": {
|
||||
"badge": {
|
||||
"title": "Badge",
|
||||
"type": "string"
|
||||
},
|
||||
"db_host": {
|
||||
"title": "Db Host",
|
||||
"type": "string"
|
||||
},
|
||||
"db_name": {
|
||||
"title": "Db Name",
|
||||
"type": "string"
|
||||
},
|
||||
"db_pass": {
|
||||
"title": "Db Pass",
|
||||
"type": "string"
|
||||
},
|
||||
"db_port": {
|
||||
"title": "Db Port",
|
||||
"type": "number"
|
||||
},
|
||||
"db_schema": {
|
||||
"title": "Db Schema",
|
||||
"type": "string"
|
||||
},
|
||||
"db_ssl": {
|
||||
"title": "Db Ssl",
|
||||
"type": "boolean"
|
||||
},
|
||||
"db_user": {
|
||||
"title": "Db User",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
"organization_id": {
|
||||
"title": "Organization Id",
|
||||
"type": "number"
|
||||
},
|
||||
"ref": {
|
||||
"title": "Ref",
|
||||
"type": "string"
|
||||
},
|
||||
"stripe_subscription_id": {
|
||||
"title": "Stripe Subscription Id",
|
||||
"type": "string"
|
||||
},
|
||||
"supabase_url": {
|
||||
"title": "Supabase Url",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"title": "Version",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "inserted_at", "updated_at", "status", "version"],
|
||||
"properties": {
|
||||
"app_id": {
|
||||
"title": "App Id",
|
||||
"type": "number"
|
||||
},
|
||||
"config": {
|
||||
"title": "Config",
|
||||
"type": "object"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"project_id": {
|
||||
"title": "Project Id",
|
||||
"type": "number"
|
||||
},
|
||||
"status": {
|
||||
"title": "Status",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"INACTIVE",
|
||||
"ACTIVE_HEALTHY",
|
||||
"ACTIVE_UNHEALTHY",
|
||||
"COMING_UP",
|
||||
"UNKNOWN",
|
||||
"GOING_DOWN",
|
||||
"INIT_FAILED",
|
||||
"REMOVED"
|
||||
]
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"title": "Version",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "auth0_id", "inserted_at", "updated_at", "username", "is_alpha_user"],
|
||||
"properties": {
|
||||
"auth0_id": {
|
||||
"title": "Auth0 Id",
|
||||
"type": "string"
|
||||
},
|
||||
"data": {
|
||||
"title": "Data",
|
||||
"type": "object"
|
||||
},
|
||||
"first_name": {
|
||||
"title": "First Name",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "number"
|
||||
},
|
||||
"inserted_at": {
|
||||
"title": "Inserted At",
|
||||
"type": "string"
|
||||
},
|
||||
"is_alpha_user": {
|
||||
"title": "Is Alpha User",
|
||||
"type": "boolean"
|
||||
},
|
||||
"last_name": {
|
||||
"title": "Last Name",
|
||||
"type": "string"
|
||||
},
|
||||
"mobile": {
|
||||
"title": "Mobile",
|
||||
"type": "string"
|
||||
},
|
||||
"primary_email": {
|
||||
"title": "Primary Email",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"title": "Updated At",
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"title": "Username",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
-67
@@ -727,7 +727,6 @@
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"@zip.js/zip.js": "^2.7.29",
|
||||
"ai": "^2.2.26",
|
||||
"ajv": "^8.6.3",
|
||||
"awesome-debounce-promise": "^2.1.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"clsx": "^1.2.1",
|
||||
@@ -788,8 +787,6 @@
|
||||
"sql-formatter": "^12.2.0",
|
||||
"sqlstring": "^2.3.2",
|
||||
"ui": "*",
|
||||
"uniforms-bootstrap4": "^3.6.2",
|
||||
"uniforms-bridge-json-schema": "^3.6.2",
|
||||
"uuid": "^9.0.1",
|
||||
"valtio": "^1.11.2",
|
||||
"yup": "^0.32.11",
|
||||
@@ -853,20 +850,6 @@
|
||||
"glob": "7.1.7"
|
||||
}
|
||||
},
|
||||
"apps/studio/node_modules/ajv": {
|
||||
"version": "8.12.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"apps/studio/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"license": "Python-2.0"
|
||||
@@ -979,10 +962,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"apps/studio/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"apps/studio/node_modules/resolve": {
|
||||
"version": "2.0.0-next.5",
|
||||
"dev": true,
|
||||
@@ -33588,52 +33567,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/uniforms": {
|
||||
"version": "3.10.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"invariant": "^2.0.0",
|
||||
"lodash": "^4.0.0",
|
||||
"tslib": "^2.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vazco/uniforms?sponsor=1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^17.0.0 || ^16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uniforms-bootstrap4": {
|
||||
"version": "3.10.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"classnames": "^2.0.0",
|
||||
"invariant": "^2.0.0",
|
||||
"lodash": "^4.0.0",
|
||||
"tslib": "^2.2.0",
|
||||
"uniforms": "^3.10.2",
|
||||
"warning": "^4.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vazco/uniforms?sponsor=1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^17.0.0 || ^16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uniforms-bridge-json-schema": {
|
||||
"version": "3.10.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"invariant": "^2.0.0",
|
||||
"lodash": "^4.0.0",
|
||||
"tslib": "^2.2.0",
|
||||
"uniforms": "^3.10.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vazco/uniforms?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/unique-filename": {
|
||||
"version": "1.1.1",
|
||||
"license": "ISC",
|
||||
|
||||
Reference in new issue
Block a user