@@ -337,7 +238,7 @@ const refreshData = async(evt: RefresherCustomEvent | null = null) => {
{{ p.name }}
- {{ p.description }}
+ {{ t(p.description) }}
diff --git a/src/pages/onboarding/confirm_email.vue b/src/pages/onboarding/confirm_email.vue
index cb93946282..ec5b126e7b 100644
--- a/src/pages/onboarding/confirm_email.vue
+++ b/src/pages/onboarding/confirm_email.vue
@@ -11,7 +11,7 @@ const { t } = useI18n()
-
+
{{ t('register.confirm-email') }}
diff --git a/src/services/crips.ts b/src/services/crips.ts
index f4a4df8b95..0b32ee7705 100644
--- a/src/services/crips.ts
+++ b/src/services/crips.ts
@@ -5,6 +5,15 @@ const CapacitorCrisp = new CapacitorCrispWeb()
export const setUserId = (uuid: string): void => {
CapacitorCrisp.setString({ key: 'user-uuid', value: uuid })
}
+
+export const setUser = (data: {
+ nickname?: string
+ phone?: string
+ email?: string
+ avatar?: string
+}): void => {
+ CapacitorCrisp.setUser(data)
+}
export const setVersion = (version: string): void => {
CapacitorCrisp.setString({ key: 'webVersion', value: version })
}
diff --git a/src/services/date.ts b/src/services/date.ts
new file mode 100644
index 0000000000..8b6bd8bc42
--- /dev/null
+++ b/src/services/date.ts
@@ -0,0 +1,5 @@
+import dayjs from 'dayjs'
+
+export const formatDate = (date: string | undefined) => {
+ return dayjs(date).format('YYYY-MM-DD HH:mm')
+}
diff --git a/src/services/plans.ts b/src/services/plans.ts
new file mode 100644
index 0000000000..30efe4f5d5
--- /dev/null
+++ b/src/services/plans.ts
@@ -0,0 +1,32 @@
+import { definitions } from "~/types/supabase"
+
+export interface Stats {
+ apps: number
+ channels: number
+ versions: number
+ sharedChannels: number
+ updates: number
+}
+export interface Plan extends Stats {
+ id: string
+ name: string
+ description: string
+ price: {
+ monthly: number
+ yearly: number
+ }
+ abtest: boolean
+ progressiveDeploy: boolean
+}
+
+export interface PlanData {
+ plan: string,
+ planSuggest: string,
+ stats: definitions['app_stats'][],
+ payment: definitions['stripe_info'] | null,
+ canUseMore: boolean
+ }
+ export interface PlanRes extends PlanData {
+ trialDaysLeft: 0,
+ AllPlans: Record,
+ }
\ No newline at end of file
diff --git a/src/services/stripe.ts b/src/services/stripe.ts
index 8c842683db..58dd3368fa 100644
--- a/src/services/stripe.ts
+++ b/src/services/stripe.ts
@@ -12,17 +12,19 @@ export const openPortal = async() => {
})
try {
await loading.present()
- const response = await fetch('https://capgo.app/api/stripe_portal', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'authorization': session.access_token,
- },
- })
- const res = await response.json()
+ const resp = await supabase.functions.invoke('stripe_portal', {})
+ console.error('stripe_portal', resp)
+ // const response = await fetch('https://capgo.app/api/stripe_portal', {
+ // method: 'POST',
+ // headers: {
+ // 'Content-Type': 'application/json',
+ // 'authorization': session.access_token,
+ // },
+ // })
+ // const res = await response.json()
await loading.dismiss()
- if (res && res.url)
- window.open(res.url, '_blank')
+ if (!resp.error && resp.data && resp.data.url)
+ window.open(resp.data.url, '_blank')
}
catch (error) {
console.error(error)
diff --git a/src/stores/main.ts b/src/stores/main.ts
index a2b94db236..db6af83896 100644
--- a/src/stores/main.ts
+++ b/src/stores/main.ts
@@ -3,11 +3,13 @@ import { acceptHMRUpdate, defineStore } from 'pinia'
import { ref } from 'vue'
import type { definitions } from '~/types/supabase'
import { useSupabase } from '~/services/supabase'
+import { PlanRes } from '~/services/plans'
export const useMainStore = defineStore('main', () => {
const auth = ref()
const path = ref('')
const user = ref()
+ const myPlan = ref()
const logout = async() => {
return new Promise((resolve) => {
@@ -16,6 +18,7 @@ export const useMainStore = defineStore('main', () => {
if (event === 'SIGNED_OUT') {
auth.value = undefined
user.value = undefined
+ myPlan.value = undefined
resolve()
}
})
@@ -27,6 +30,7 @@ export const useMainStore = defineStore('main', () => {
}
return {
auth,
+ myPlan,
user,
path,
logout,
diff --git a/src/styles/main.css b/src/styles/main.css
index 009fac6d9a..cdb8839aef 100755
--- a/src/styles/main.css
+++ b/src/styles/main.css
@@ -186,16 +186,16 @@ http://ionicframework.com/docs/theming/ */
--ion-color-step-900: #e6e6e6;
--ion-color-step-950: #f2f2f2;
- --ion-item-background: theme('colors.black.DEFAULT');
+ --IonItem-background: theme('colors.black.DEFAULT');
--ion-card-background: #1c1c1d;
}
.ios body ion-modal {
--ion-background-color: var(--ion-color-step-100);
- --ion-toolbar-background: var(--ion-color-step-150);
- --ion-toolbar-border-color: var(--ion-color-step-250);
- --ion-item-background: var(--ion-color-step-150);
+ --IonToolbar-background: var(--ion-color-step-150);
+ --IonToolbar-border-color: var(--ion-color-step-250);
+ --IonItem-background: var(--ion-color-step-150);
}
/*
@@ -232,9 +232,9 @@ http://ionicframework.com/docs/theming/ */
--ion-color-step-900: #e7e7e7;
--ion-color-step-950: #f3f3f3;
- --ion-item-background: #1e1e1e;
+ --IonItem-background: #1e1e1e;
- --ion-toolbar-background: #1f1f1f;
+ --IonToolbar-background: #1f1f1f;
--ion-tab-bar-background: #1f1f1f;
diff --git a/src/types/supabase.ts b/src/types/supabase.ts
index 7e8acd20f0..22f486ab0f 100644
--- a/src/types/supabase.ts
+++ b/src/types/supabase.ts
@@ -114,6 +114,234 @@ export interface paths {
};
};
};
+ "/app_stats": {
+ get: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats.app_id"];
+ user_id?: parameters["rowFilter.app_stats.user_id"];
+ created_at?: parameters["rowFilter.app_stats.created_at"];
+ updated_at?: parameters["rowFilter.app_stats.updated_at"];
+ channels?: parameters["rowFilter.app_stats.channels"];
+ mlu?: parameters["rowFilter.app_stats.mlu"];
+ versions?: parameters["rowFilter.app_stats.versions"];
+ shared?: parameters["rowFilter.app_stats.shared"];
+ mlu_real?: parameters["rowFilter.app_stats.mlu_real"];
+ devices?: parameters["rowFilter.app_stats.devices"];
+ date_id?: parameters["rowFilter.app_stats.date_id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["app_stats"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** app_stats */
+ app_stats?: definitions["app_stats"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats.app_id"];
+ user_id?: parameters["rowFilter.app_stats.user_id"];
+ created_at?: parameters["rowFilter.app_stats.created_at"];
+ updated_at?: parameters["rowFilter.app_stats.updated_at"];
+ channels?: parameters["rowFilter.app_stats.channels"];
+ mlu?: parameters["rowFilter.app_stats.mlu"];
+ versions?: parameters["rowFilter.app_stats.versions"];
+ shared?: parameters["rowFilter.app_stats.shared"];
+ mlu_real?: parameters["rowFilter.app_stats.mlu_real"];
+ devices?: parameters["rowFilter.app_stats.devices"];
+ date_id?: parameters["rowFilter.app_stats.date_id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats.app_id"];
+ user_id?: parameters["rowFilter.app_stats.user_id"];
+ created_at?: parameters["rowFilter.app_stats.created_at"];
+ updated_at?: parameters["rowFilter.app_stats.updated_at"];
+ channels?: parameters["rowFilter.app_stats.channels"];
+ mlu?: parameters["rowFilter.app_stats.mlu"];
+ versions?: parameters["rowFilter.app_stats.versions"];
+ shared?: parameters["rowFilter.app_stats.shared"];
+ mlu_real?: parameters["rowFilter.app_stats.mlu_real"];
+ devices?: parameters["rowFilter.app_stats.devices"];
+ date_id?: parameters["rowFilter.app_stats.date_id"];
+ };
+ body: {
+ /** app_stats */
+ app_stats?: definitions["app_stats"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/app_stats_onprem": {
+ get: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats_onprem.app_id"];
+ user_id?: parameters["rowFilter.app_stats_onprem.user_id"];
+ created_at?: parameters["rowFilter.app_stats_onprem.created_at"];
+ updated_at?: parameters["rowFilter.app_stats_onprem.updated_at"];
+ channels?: parameters["rowFilter.app_stats_onprem.channels"];
+ mlu?: parameters["rowFilter.app_stats_onprem.mlu"];
+ versions?: parameters["rowFilter.app_stats_onprem.versions"];
+ shared?: parameters["rowFilter.app_stats_onprem.shared"];
+ mlu_real?: parameters["rowFilter.app_stats_onprem.mlu_real"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["app_stats_onprem"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** app_stats_onprem */
+ app_stats_onprem?: definitions["app_stats_onprem"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats_onprem.app_id"];
+ user_id?: parameters["rowFilter.app_stats_onprem.user_id"];
+ created_at?: parameters["rowFilter.app_stats_onprem.created_at"];
+ updated_at?: parameters["rowFilter.app_stats_onprem.updated_at"];
+ channels?: parameters["rowFilter.app_stats_onprem.channels"];
+ mlu?: parameters["rowFilter.app_stats_onprem.mlu"];
+ versions?: parameters["rowFilter.app_stats_onprem.versions"];
+ shared?: parameters["rowFilter.app_stats_onprem.shared"];
+ mlu_real?: parameters["rowFilter.app_stats_onprem.mlu_real"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats_onprem.app_id"];
+ user_id?: parameters["rowFilter.app_stats_onprem.user_id"];
+ created_at?: parameters["rowFilter.app_stats_onprem.created_at"];
+ updated_at?: parameters["rowFilter.app_stats_onprem.updated_at"];
+ channels?: parameters["rowFilter.app_stats_onprem.channels"];
+ mlu?: parameters["rowFilter.app_stats_onprem.mlu"];
+ versions?: parameters["rowFilter.app_stats_onprem.versions"];
+ shared?: parameters["rowFilter.app_stats_onprem.shared"];
+ mlu_real?: parameters["rowFilter.app_stats_onprem.mlu_real"];
+ };
+ body: {
+ /** app_stats_onprem */
+ app_stats_onprem?: definitions["app_stats_onprem"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
"/app_versions": {
get: {
parameters: {
@@ -554,6 +782,7 @@ export interface paths {
public?: parameters["rowFilter.channels.public"];
disableAutoUpdateUnderNative?: parameters["rowFilter.channels.disableAutoUpdateUnderNative"];
disableAutoUpdateToMajor?: parameters["rowFilter.channels.disableAutoUpdateToMajor"];
+ beta?: parameters["rowFilter.channels.beta"];
/** Filtering Columns */
select?: parameters["select"];
/** Ordering */
@@ -614,6 +843,7 @@ export interface paths {
public?: parameters["rowFilter.channels.public"];
disableAutoUpdateUnderNative?: parameters["rowFilter.channels.disableAutoUpdateUnderNative"];
disableAutoUpdateToMajor?: parameters["rowFilter.channels.disableAutoUpdateToMajor"];
+ beta?: parameters["rowFilter.channels.beta"];
};
header: {
/** Preference */
@@ -638,6 +868,7 @@ export interface paths {
public?: parameters["rowFilter.channels.public"];
disableAutoUpdateUnderNative?: parameters["rowFilter.channels.disableAutoUpdateUnderNative"];
disableAutoUpdateToMajor?: parameters["rowFilter.channels.disableAutoUpdateToMajor"];
+ beta?: parameters["rowFilter.channels.beta"];
};
body: {
/** channels */
@@ -1093,9 +1324,9 @@ export interface paths {
action?: parameters["rowFilter.stats_onprem.action"];
device_id?: parameters["rowFilter.stats_onprem.device_id"];
version_build?: parameters["rowFilter.stats_onprem.version_build"];
- version?: parameters["rowFilter.stats_onprem.version"];
app_id?: parameters["rowFilter.stats_onprem.app_id"];
updated_at?: parameters["rowFilter.stats_onprem.updated_at"];
+ version?: parameters["rowFilter.stats_onprem.version"];
/** Filtering Columns */
select?: parameters["select"];
/** Ordering */
@@ -1152,9 +1383,9 @@ export interface paths {
action?: parameters["rowFilter.stats_onprem.action"];
device_id?: parameters["rowFilter.stats_onprem.device_id"];
version_build?: parameters["rowFilter.stats_onprem.version_build"];
- version?: parameters["rowFilter.stats_onprem.version"];
app_id?: parameters["rowFilter.stats_onprem.app_id"];
updated_at?: parameters["rowFilter.stats_onprem.updated_at"];
+ version?: parameters["rowFilter.stats_onprem.version"];
};
header: {
/** Preference */
@@ -1175,9 +1406,9 @@ export interface paths {
action?: parameters["rowFilter.stats_onprem.action"];
device_id?: parameters["rowFilter.stats_onprem.device_id"];
version_build?: parameters["rowFilter.stats_onprem.version_build"];
- version?: parameters["rowFilter.stats_onprem.version"];
app_id?: parameters["rowFilter.stats_onprem.app_id"];
updated_at?: parameters["rowFilter.stats_onprem.updated_at"];
+ version?: parameters["rowFilter.stats_onprem.version"];
};
body: {
/** stats_onprem */
@@ -1204,6 +1435,7 @@ export interface paths {
customer_id?: parameters["rowFilter.stripe_info.customer_id"];
status?: parameters["rowFilter.stripe_info.status"];
product_id?: parameters["rowFilter.stripe_info.product_id"];
+ trial_at?: parameters["rowFilter.stripe_info.trial_at"];
/** Filtering Columns */
select?: parameters["select"];
/** Ordering */
@@ -1260,6 +1492,7 @@ export interface paths {
customer_id?: parameters["rowFilter.stripe_info.customer_id"];
status?: parameters["rowFilter.stripe_info.status"];
product_id?: parameters["rowFilter.stripe_info.product_id"];
+ trial_at?: parameters["rowFilter.stripe_info.trial_at"];
};
header: {
/** Preference */
@@ -1280,6 +1513,7 @@ export interface paths {
customer_id?: parameters["rowFilter.stripe_info.customer_id"];
status?: parameters["rowFilter.stripe_info.status"];
product_id?: parameters["rowFilter.stripe_info.product_id"];
+ trial_at?: parameters["rowFilter.stripe_info.trial_at"];
};
body: {
/** stripe_info */
@@ -1416,6 +1650,28 @@ export interface paths {
};
};
};
+ "/rpc/is_app_owner": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: character varying */
+ appid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
"/rpc/get_max_channel": {
post: {
parameters: {
@@ -1460,6 +1716,28 @@ export interface paths {
};
};
};
+ "/rpc/is_app_shared": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: character varying */
+ appid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
"/rpc/get_max_shared": {
post: {
parameters: {
@@ -1500,6 +1778,28 @@ export interface paths {
};
};
};
+ "/rpc/is_version_shared": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: bigint */
+ versionid: number;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
"/rpc/get_dl_by_month": {
post: {
parameters: {
@@ -1552,6 +1852,77 @@ export interface definitions {
*/
updated_at?: string;
};
+ app_stats: {
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /** Format: uuid */
+ user_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: smallint */
+ channels: number;
+ /** Format: bigint */
+ mlu: number;
+ /** Format: bigint */
+ versions: number;
+ /** Format: bigint */
+ shared: number;
+ /** Format: bigint */
+ mlu_real: number;
+ /** Format: bigint */
+ devices: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ * @default 2022-05
+ */
+ date_id: string;
+ };
+ app_stats_onprem: {
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /** Format: uuid */
+ user_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: smallint */
+ channels?: number;
+ /** Format: bigint */
+ mlu?: number;
+ /** Format: bigint */
+ versions?: number;
+ /** Format: bigint */
+ shared?: number;
+ /** Format: bigint */
+ mlu_real?: number;
+ };
app_versions: {
/**
* Format: bigint
@@ -1742,6 +2113,8 @@ export interface definitions {
* @default true
*/
disableAutoUpdateToMajor: boolean;
+ /** Format: boolean */
+ beta?: boolean;
};
devices: {
/**
@@ -1921,12 +2294,6 @@ export interface definitions {
device_id: string;
/** Format: text */
version_build: string;
- /**
- * Format: bigint
- * @description Note:
- * This is a Foreign Key to `app_versions.id`.
- */
- version: number;
/** Format: character varying */
app_id: string;
/**
@@ -1934,18 +2301,20 @@ export interface definitions {
* @default now()
*/
updated_at?: string;
+ /** Format: character varying */
+ version: string;
};
stripe_info: {
/**
* Format: timestamp with time zone
* @default now()
*/
- created_at?: string;
+ created_at: string;
/**
* Format: timestamp with time zone
* @default now()
*/
- updated_at?: string;
+ updated_at: string;
/** Format: character varying */
subscription_id?: string;
/**
@@ -1967,6 +2336,11 @@ export interface definitions {
| "canceled";
/** Format: character varying */
product_id?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ trial_at: string;
};
users: {
/**
@@ -2053,6 +2427,50 @@ export interface parameters {
"rowFilter.apikeys.mode": string;
/** Format: timestamp with time zone */
"rowFilter.apikeys.updated_at": string;
+ /** @description app_stats */
+ "body.app_stats": definitions["app_stats"];
+ /** Format: character varying */
+ "rowFilter.app_stats.app_id": string;
+ /** Format: uuid */
+ "rowFilter.app_stats.user_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats.updated_at": string;
+ /** Format: smallint */
+ "rowFilter.app_stats.channels": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.mlu": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.versions": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.shared": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.mlu_real": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.devices": string;
+ /** Format: character varying */
+ "rowFilter.app_stats.date_id": string;
+ /** @description app_stats_onprem */
+ "body.app_stats_onprem": definitions["app_stats_onprem"];
+ /** Format: character varying */
+ "rowFilter.app_stats_onprem.app_id": string;
+ /** Format: uuid */
+ "rowFilter.app_stats_onprem.user_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats_onprem.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats_onprem.updated_at": string;
+ /** Format: smallint */
+ "rowFilter.app_stats_onprem.channels": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.mlu": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.versions": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.shared": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.mlu_real": string;
/** @description app_versions */
"body.app_versions": definitions["app_versions"];
/** Format: bigint */
@@ -2143,6 +2561,8 @@ export interface parameters {
"rowFilter.channels.disableAutoUpdateUnderNative": string;
/** Format: boolean */
"rowFilter.channels.disableAutoUpdateToMajor": string;
+ /** Format: boolean */
+ "rowFilter.channels.beta": string;
/** @description devices */
"body.devices": definitions["devices"];
/** Format: timestamp with time zone */
@@ -2227,12 +2647,12 @@ export interface parameters {
"rowFilter.stats_onprem.device_id": string;
/** Format: text */
"rowFilter.stats_onprem.version_build": string;
- /** Format: bigint */
- "rowFilter.stats_onprem.version": string;
/** Format: character varying */
"rowFilter.stats_onprem.app_id": string;
/** Format: timestamp with time zone */
"rowFilter.stats_onprem.updated_at": string;
+ /** Format: character varying */
+ "rowFilter.stats_onprem.version": string;
/** @description stripe_info */
"body.stripe_info": definitions["stripe_info"];
/** Format: timestamp with time zone */
@@ -2247,6 +2667,8 @@ export interface parameters {
"rowFilter.stripe_info.status": string;
/** Format: character varying */
"rowFilter.stripe_info.product_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stripe_info.trial_at": string;
/** @description users */
"body.users": definitions["users"];
/** Format: timestamp with time zone */
diff --git a/supabase/.env.exemple b/supabase/.env.exemple
new file mode 100644
index 0000000000..94d8ac454b
--- /dev/null
+++ b/supabase/.env.exemple
@@ -0,0 +1,6 @@
+STRIPE_WEBHOOK_SECRET=test
+STRIPE_SECRET_KEY=test
+API_SECRET=test
+PLAN_MAKER=test
+PLAN_SOLO=test
+PLAN_TEAM=test
\ No newline at end of file
diff --git a/supabase/config.toml b/supabase/config.toml
new file mode 100644
index 0000000000..7b812666d2
--- /dev/null
+++ b/supabase/config.toml
@@ -0,0 +1,60 @@
+# A string used to distinguish different Supabase projects on the same host. Defaults to the working
+# directory name when running `supabase init`.
+project_id = "capgo"
+
+[api]
+# Port to use for the API URL.
+port = 54321
+# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
+# endpoints. public and storage are always included.
+schemas = []
+# Extra schemas to add to the search_path of every request.
+extra_search_path = ["extensions"]
+# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
+# for accidental or malicious requests.
+max_rows = 1000
+
+[db]
+# Port to use for the local database URL.
+port = 54322
+# The database major version to use. This has to be the same as your remote database's. Run `SHOW
+# server_version;` on the remote database to check.
+major_version = 14
+
+[studio]
+# Port to use for Supabase Studio.
+port = 54323
+
+# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
+# are monitored, and you can view the emails that would have been sent from the web interface.
+[inbucket]
+# Port to use for the email testing server web interface.
+port = 54324
+
+[auth]
+# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
+# in emails.
+site_url = "http://localhost:3000"
+# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
+additional_redirect_urls = ["https://localhost:3000"]
+# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 seconds (one
+# week).
+jwt_expiry = 3600
+# Allow/disallow new user signups to your project.
+enable_signup = true
+
+[auth.email]
+# Allow/disallow new user signups via email to your project.
+enable_signup = true
+# 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.
+double_confirm_changes = true
+# If enabled, users need to confirm their email address before signing in.
+enable_confirmations = false
+
+# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
+# `discord`, `facebook`, `github`, `gitlab`, `google`, `twitch`, `twitter`, `slack`, `spotify`.
+[auth.external.apple]
+enabled = false
+client_id = ""
+secret = ""
diff --git a/supabase/functions/_utils/plans.ts b/supabase/functions/_utils/plans.ts
new file mode 100644
index 0000000000..c35e57acf8
--- /dev/null
+++ b/supabase/functions/_utils/plans.ts
@@ -0,0 +1,202 @@
+import { supabaseAdmin } from './supabase.ts'
+import type { definitions } from './types_supabase.ts'
+import dayjs from 'https://cdn.skypack.dev/dayjs'
+
+export interface PlanData {
+ plan: string,
+ planSuggest: string,
+ payment?: definitions['stripe_info'] | null,
+ canUseMore: boolean
+}
+export interface PlanRes extends PlanData {
+ trialDaysLeft: number,
+ stats: definitions['app_stats'][],
+ AllPlans: Record,
+}
+
+export interface Stats {
+ apps: number
+ channels: number
+ versions: number
+ sharedChannels: number
+ updates: number
+}
+export interface Plan extends Stats {
+ id: string
+ name: string
+ description: string
+ price: {
+ monthly: number
+ yearly: number
+ }
+ abtest: boolean
+ progressiveDeploy: boolean
+}
+
+export const plans: Record = {
+ free: {
+ id: 'free',
+ name: 'Free',
+ description: 'plan.free.desc',
+ price: {
+ monthly: 0,
+ yearly: 0,
+ },
+ apps: 1,
+ channels: 1,
+ updates: 500,
+ versions: 10,
+ sharedChannels: 0,
+ abtest: false,
+ progressiveDeploy: false,
+ },
+ solo: {
+ id: Deno.env.get('PLAN_SOLO') || 'solo',
+ name: 'Solo',
+ description: 'plan.solo.desc',
+ price: {
+ monthly: 14,
+ yearly: 146,
+ },
+ apps: 1,
+ channels: 2,
+ updates: 2500,
+ versions: 10,
+ sharedChannels: 0,
+ abtest: false,
+ progressiveDeploy: false,
+ },
+ maker: {
+ id: Deno.env.get('PLAN_MAKER') || 'maker',
+ name: 'Maker',
+ description: 'plan.maker.desc',
+ price: {
+ monthly: 39,
+ yearly: 389,
+ },
+ apps: 3,
+ channels: 10,
+ updates: 25000,
+ versions: 100,
+ sharedChannels: 10,
+ abtest: false,
+ progressiveDeploy: false,
+ },
+ team: {
+ id: Deno.env.get('PLAN_TEAM') || 'team',
+ name: 'Team',
+ description: 'plan.team.desc',
+ price: {
+ monthly: 99,
+ yearly: 998,
+ },
+ apps: 10,
+ channels: 50,
+ updates: 250000,
+ versions: 1000,
+ sharedChannels: 1000,
+ abtest: true,
+ progressiveDeploy: true,
+ },
+}
+
+export const isAllowInMyPlan = (myPlan: Plan, app_stats: definitions['app_stats'][]): boolean => {
+ if (app_stats && app_stats.length) {
+ // find biggest number of versions
+ const biggestChannels = app_stats.reduce((acc, app) => Math.max(acc, app.channels), 0)
+ const biggestVersions = app_stats.reduce((acc, app) => Math.max(acc, app.versions), 0)
+ const biggestUpdates = app_stats.reduce((acc, cur) => Math.max(acc, Math.max(cur.mlu, cur.mlu_real)), 0)
+ return app_stats.length < myPlan.apps && biggestChannels < myPlan.channels && biggestVersions < myPlan.versions && biggestUpdates < myPlan.updates
+ }
+ return false
+}
+
+export const getMystats = async(user_id: string): Promise => {
+ const { data: app_stats } = await supabaseAdmin
+ .from('app_stats')
+ .select()
+ .eq('user_id', user_id)
+ return app_stats || []
+}
+
+export const getMyPlan = async(user_id: string, stats: definitions['app_stats'][]): Promise => {
+ console.log('user', user_id)
+ let user: definitions['users']
+ let payment: definitions['stripe_info'] | null = null
+ const { data: users } = await supabaseAdmin
+ .from('users')
+ .select()
+ .eq('id', user_id)
+ if (users && users.length)
+ user = users[0]
+ else
+ return Promise.reject(Error('no user found'))
+ if (!user?.customer_id)
+ return Promise.reject(Error('no customer_id'))
+ const { data } = await supabaseAdmin
+ .from('stripe_info')
+ .select()
+ .eq('customer_id', user.customer_id)
+ let product_id = user.created_at && dayjs(user.created_at!).add(30, 'day').isAfter(dayjs()) ? (Deno.env.get('PLAN_TEAM') || 'team') : 'free'
+ if (data && data.length && data[0].product_id) {
+ product_id = data[0].product_id
+ payment = data[0]
+ }
+ const current = Object.values(plans)
+ .find((plan) => {
+ if (plan.id === product_id)
+ return plan
+ return false
+ })
+ if (current) {
+ let planSuggest = Deno.env.get('PLAN_TEAM') || 'team'
+ const found = Object.values(plans).find(plan => stats.length < plan.apps
+ && stats.reduce((acc, cur) => Math.max(acc, cur.channels), 0) < plan.channels
+ && stats.reduce((acc, cur) => Math.max(acc, cur.versions), 0) < plan.versions
+ && stats.reduce((acc, cur) => Math.max(acc, cur.shared), 0) < plan.sharedChannels
+ && stats.reduce((acc, cur) => Math.max(acc, Math.max(cur.mlu, cur.mlu_real)), 0) < plan.updates)
+ if (found)
+ planSuggest = found.id
+ const canUseMore = await isAllowInMyPlan(current, stats)
+ return { plan: current.id, payment, canUseMore, planSuggest }
+ }
+ return Promise.reject(Error('no data'))
+}
+
+export const currentPaymentstatus = async(user: definitions['users']): Promise => {
+ try {
+ const stats = await getMystats(user.id)
+ const myPlan = await getMyPlan(user.id, stats)
+ const res: PlanRes = {
+ stats,
+ payment: myPlan.payment,
+ plan: myPlan.plan,
+ planSuggest: myPlan.planSuggest,
+ trialDaysLeft: 30,
+ canUseMore: true,
+ AllPlans: plans,
+ }
+ if (res.plan === 'free') {
+ const created_at = (new Date(myPlan.payment?.trial_at!)).getTime()
+ const daysSinceCreated = ((new Date()).getTime() - created_at) / (1000 * 3600 * 24)
+ if (daysSinceCreated <= 30) {
+ res.trialDaysLeft = 30 - daysSinceCreated
+ }
+ else {
+ res.trialDaysLeft = 0
+ }
+ }
+ return res
+ }
+ catch (error) {
+ console.log('currentPaymentstatus error', error)
+ return {
+ stats: [],
+ canUseMore: false,
+ trialDaysLeft: 0,
+ AllPlans: plans,
+ plan: 'free',
+ planSuggest: 'solo',
+ }
+ }
+}
diff --git a/supabase/functions/_utils/stripe.ts b/supabase/functions/_utils/stripe.ts
new file mode 100644
index 0000000000..813a3ea0f9
--- /dev/null
+++ b/supabase/functions/_utils/stripe.ts
@@ -0,0 +1,122 @@
+import dayjs from 'https://cdn.skypack.dev/dayjs'
+import Stripe from 'https://esm.sh/stripe@9.1.0?no-check&target=deno'
+import type { definitions } from './types_supabase.ts'
+
+export const parseStripeEvent = async(key: string, body: string, signature: string, secret: string) => {
+ const stripe = new Stripe(key, {
+ apiVersion: '2020-08-27',
+ httpClient: Stripe.createFetchHttpClient(),
+ })
+ const event = await stripe.webhooks.constructEventAsync(body, signature, secret, undefined, Stripe.createSubtleCryptoProvider())
+ return event
+}
+
+export const createPortal = async(key: string, customerId: string, callbackUrl: string) => {
+ const stripe = new Stripe(key, {
+ apiVersion: '2020-08-27',
+ httpClient: Stripe.createFetchHttpClient(),
+ })
+ const link = await stripe.billingPortal.sessions.create({
+ customer: customerId,
+ return_url: callbackUrl,
+ })
+ return link
+}
+
+export const createCheckout = async(key: string, customerId: string, reccurence: string, planId: string, successUrl: string, cancelUrl: string) => {
+ const stripe = new Stripe(key, {
+ apiVersion: '2020-08-27',
+ httpClient: Stripe.createFetchHttpClient(),
+ })
+ // eslint-disable-next-line no-console
+ // console.log('planId', planId)
+ let priceId = null
+ try {
+ const prices = await stripe.prices.search({
+ query: `product:'${planId}'`,
+ })
+ prices.data.forEach((price: any) => {
+ // eslint-disable-next-line no-console
+ // console.log('price', JSON.stringify(price))
+ if (price.recurring.interval === reccurence && price.active)
+ priceId = price.id
+ })
+ }
+ catch (err) {
+ // eslint-disable-next-line no-console
+ console.log('err', err)
+ }
+ if (!priceId)
+ Promise.reject(new Error('Cannot find price'))
+ const checkoutData = {
+ billing_address_collection: 'auto',
+ line_items: [{
+ price: priceId,
+ quantity: 1,
+ }],
+ mode: 'subscription',
+ customer: customerId,
+ success_url: `${successUrl}?session_id={CHECKOUT_SESSION_ID}`,
+ cancel_url: cancelUrl,
+ }
+ // eslint-disable-next-line no-console
+ // console.log('checkoutData', checkoutData)
+ const session = await stripe.checkout.sessions.create(checkoutData)
+ return session
+}
+
+export const deleteSub = async(key: string, subscriptionId: string) => {
+ const stripe = new Stripe(key, {
+ apiVersion: '2020-08-27',
+ httpClient: Stripe.createFetchHttpClient(),
+ })
+ try {
+ const res = await stripe.subscriptions.del(subscriptionId)
+ return res
+ }
+ catch (err) {
+ return err
+ }
+}
+export const createCustomer = async(key: string, email: string) => {
+ const stripe = new Stripe(key, {
+ apiVersion: '2020-08-27',
+ httpClient: Stripe.createFetchHttpClient(),
+ })
+ return await stripe.customers.create({
+ email,
+ })
+}
+
+export const extractDataEvent = (event: any): definitions['stripe_info'] => {
+ const data: definitions['stripe_info'] = {
+ product_id: undefined,
+ subscription_id: undefined,
+ customer_id: '',
+ updated_at: dayjs().toISOString(),
+ trial_at: dayjs().toISOString(),
+ created_at: dayjs().toISOString(),
+ status: undefined,
+ }
+ // eslint-disable-next-line no-console
+ console.log('event', JSON.stringify(event, null, 2))
+ if (event && event.data && event.data.object) {
+ if (event.type === 'customer.subscription.updated') {
+ const subscription = event.data.object as any
+ data.product_id = subscription.items.data.length ? subscription.items.data[0].plan.id : undefined
+ data.status = subscription.cancel_at ? 'canceled' : 'succeeded'
+ data.subscription_id = subscription.id
+ data.customer_id = String(subscription.customer)
+ }
+ else if (event.type === 'customer.subscription.deleted') {
+ const charge = event.data.object as any
+ data.status = 'canceled'
+ data.customer_id = String(charge.customer)
+ data.subscription_id = undefined
+ }
+ else {
+ console.error('Other event', event.type, event)
+ }
+ }
+ return data
+}
diff --git a/supabase/functions/_utils/supabase.ts b/supabase/functions/_utils/supabase.ts
new file mode 100644
index 0000000000..959305b397
--- /dev/null
+++ b/supabase/functions/_utils/supabase.ts
@@ -0,0 +1,110 @@
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@^1.35.3'
+import type { definitions } from './types_supabase.ts'
+// Import Supabase client
+
+export const supabaseClient = createClient(
+ // Supabase API URL - env var exported by default.
+ Deno.env.get('SUPABASE_URL') ?? '',
+ // Supabase API ANON KEY - env var exported by default.
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
+)
+
+// WARNING: The service role key has admin priviliges and should only be used in secure server environments!
+export const supabaseAdmin = createClient(
+ Deno.env.get('SUPABASE_URL') ?? '',
+ Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '',
+)
+
+export const updateOrCreateVersion = async(update: Partial) => {
+ // eslint-disable-next-line no-console
+ console.log('updateOrCreateVersion', update)
+ const { data, error } = await supabaseAdmin
+ .from('app_versions')
+ .select()
+ .eq('app_id', update.app_id)
+ .eq('name', update.name)
+ if (data && data.length && !error) {
+ // eslint-disable-next-line no-console
+ console.log('update Version')
+ update.deleted = false
+ return supabaseAdmin
+ .from('app_versions')
+ .update(update)
+ .eq('app_id', update.app_id)
+ .eq('name', update.name)
+ }
+ else {
+ return supabaseAdmin
+ .from('app_versions')
+ .insert(update)
+ }
+}
+
+export const updateOrCreateChannel = async(update: Partial) => {
+ // eslint-disable-next-line no-console
+ console.log('updateOrCreateChannel', update)
+ if (!update.app_id || !update.name || !update.created_by) {
+ console.error('missing app_id, name, or created_by')
+ return Promise.reject(new Error('missing app_id, name, or created_by'))
+ }
+ const { data, error } = await supabaseAdmin
+ .from('channels')
+ .select()
+ .eq('app_id', update.app_id)
+ .eq('name', update.name)
+ .eq('created_by', update.created_by)
+ if (data && data.length && !error) {
+ return supabaseAdmin
+ .from('channels')
+ .update(update)
+ .eq('app_id', update.app_id)
+ .eq('name', update.name)
+ .eq('created_by', update.created_by)
+ }
+ else {
+ return supabaseAdmin
+ .from('channels')
+ .insert(update)
+ }
+}
+
+export const checkAppOwner = async(userId: string | undefined, appId: string | undefined): Promise => {
+ if (!appId || !userId)
+ return false
+ try {
+ const { data, error } = await supabaseAdmin
+ .from('apps')
+ .select()
+ .eq('user_id', userId)
+ .eq('app_id', appId)
+ if (!data || !data.length || error)
+ return false
+ return true
+ }
+ catch (error) {
+ console.error(error)
+ return false
+ }
+}
+
+export const updateOrCreateDevice = async(update: Partial) => {
+ // eslint-disable-next-line no-console
+ console.log('updateOrCreateDevice', update)
+ const { data, error } = await supabaseAdmin
+ .from('devices')
+ .select()
+ .eq('app_id', update.app_id)
+ .eq('device_id', update.device_id)
+ if (!data || !data.length || error) {
+ return supabaseAdmin
+ .from('devices')
+ .insert(update)
+ }
+ else {
+ return supabaseAdmin
+ .from('devices')
+ .update(update)
+ .eq('app_id', update.app_id)
+ .eq('device_id', update.device_id)
+ }
+}
diff --git a/supabase/functions/_utils/types.ts b/supabase/functions/_utils/types.ts
new file mode 100644
index 0000000000..caddce7660
--- /dev/null
+++ b/supabase/functions/_utils/types.ts
@@ -0,0 +1,10 @@
+export interface Customer {
+ id: string
+ stripe_customer_id: string
+}
+
+export interface JwtUser {
+ sub: string
+ email?: string
+ role: 'anon' | 'authenticated'
+}
diff --git a/supabase/functions/_utils/types_supabase.ts b/supabase/functions/_utils/types_supabase.ts
new file mode 100644
index 0000000000..7ed9fbb409
--- /dev/null
+++ b/supabase/functions/_utils/types_supabase.ts
@@ -0,0 +1,2702 @@
+/**
+ * This file was auto-generated by openapi-typescript.
+ * Do not make direct changes to the file.
+ */
+
+ export interface paths {
+ "/": {
+ get: {
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/apikeys": {
+ get: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.apikeys.id"];
+ created_at?: parameters["rowFilter.apikeys.created_at"];
+ user_id?: parameters["rowFilter.apikeys.user_id"];
+ key?: parameters["rowFilter.apikeys.key"];
+ mode?: parameters["rowFilter.apikeys.mode"];
+ updated_at?: parameters["rowFilter.apikeys.updated_at"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["apikeys"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** apikeys */
+ apikeys?: definitions["apikeys"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.apikeys.id"];
+ created_at?: parameters["rowFilter.apikeys.created_at"];
+ user_id?: parameters["rowFilter.apikeys.user_id"];
+ key?: parameters["rowFilter.apikeys.key"];
+ mode?: parameters["rowFilter.apikeys.mode"];
+ updated_at?: parameters["rowFilter.apikeys.updated_at"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.apikeys.id"];
+ created_at?: parameters["rowFilter.apikeys.created_at"];
+ user_id?: parameters["rowFilter.apikeys.user_id"];
+ key?: parameters["rowFilter.apikeys.key"];
+ mode?: parameters["rowFilter.apikeys.mode"];
+ updated_at?: parameters["rowFilter.apikeys.updated_at"];
+ };
+ body: {
+ /** apikeys */
+ apikeys?: definitions["apikeys"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/app_stats": {
+ get: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats.app_id"];
+ user_id?: parameters["rowFilter.app_stats.user_id"];
+ created_at?: parameters["rowFilter.app_stats.created_at"];
+ updated_at?: parameters["rowFilter.app_stats.updated_at"];
+ channels?: parameters["rowFilter.app_stats.channels"];
+ mlu?: parameters["rowFilter.app_stats.mlu"];
+ versions?: parameters["rowFilter.app_stats.versions"];
+ shared?: parameters["rowFilter.app_stats.shared"];
+ mlu_real?: parameters["rowFilter.app_stats.mlu_real"];
+ devices?: parameters["rowFilter.app_stats.devices"];
+ date_id?: parameters["rowFilter.app_stats.date_id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["app_stats"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** app_stats */
+ app_stats?: definitions["app_stats"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats.app_id"];
+ user_id?: parameters["rowFilter.app_stats.user_id"];
+ created_at?: parameters["rowFilter.app_stats.created_at"];
+ updated_at?: parameters["rowFilter.app_stats.updated_at"];
+ channels?: parameters["rowFilter.app_stats.channels"];
+ mlu?: parameters["rowFilter.app_stats.mlu"];
+ versions?: parameters["rowFilter.app_stats.versions"];
+ shared?: parameters["rowFilter.app_stats.shared"];
+ mlu_real?: parameters["rowFilter.app_stats.mlu_real"];
+ devices?: parameters["rowFilter.app_stats.devices"];
+ date_id?: parameters["rowFilter.app_stats.date_id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats.app_id"];
+ user_id?: parameters["rowFilter.app_stats.user_id"];
+ created_at?: parameters["rowFilter.app_stats.created_at"];
+ updated_at?: parameters["rowFilter.app_stats.updated_at"];
+ channels?: parameters["rowFilter.app_stats.channels"];
+ mlu?: parameters["rowFilter.app_stats.mlu"];
+ versions?: parameters["rowFilter.app_stats.versions"];
+ shared?: parameters["rowFilter.app_stats.shared"];
+ mlu_real?: parameters["rowFilter.app_stats.mlu_real"];
+ devices?: parameters["rowFilter.app_stats.devices"];
+ date_id?: parameters["rowFilter.app_stats.date_id"];
+ };
+ body: {
+ /** app_stats */
+ app_stats?: definitions["app_stats"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/app_stats_onprem": {
+ get: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats_onprem.app_id"];
+ user_id?: parameters["rowFilter.app_stats_onprem.user_id"];
+ created_at?: parameters["rowFilter.app_stats_onprem.created_at"];
+ updated_at?: parameters["rowFilter.app_stats_onprem.updated_at"];
+ channels?: parameters["rowFilter.app_stats_onprem.channels"];
+ mlu?: parameters["rowFilter.app_stats_onprem.mlu"];
+ versions?: parameters["rowFilter.app_stats_onprem.versions"];
+ shared?: parameters["rowFilter.app_stats_onprem.shared"];
+ mlu_real?: parameters["rowFilter.app_stats_onprem.mlu_real"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["app_stats_onprem"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** app_stats_onprem */
+ app_stats_onprem?: definitions["app_stats_onprem"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats_onprem.app_id"];
+ user_id?: parameters["rowFilter.app_stats_onprem.user_id"];
+ created_at?: parameters["rowFilter.app_stats_onprem.created_at"];
+ updated_at?: parameters["rowFilter.app_stats_onprem.updated_at"];
+ channels?: parameters["rowFilter.app_stats_onprem.channels"];
+ mlu?: parameters["rowFilter.app_stats_onprem.mlu"];
+ versions?: parameters["rowFilter.app_stats_onprem.versions"];
+ shared?: parameters["rowFilter.app_stats_onprem.shared"];
+ mlu_real?: parameters["rowFilter.app_stats_onprem.mlu_real"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ app_id?: parameters["rowFilter.app_stats_onprem.app_id"];
+ user_id?: parameters["rowFilter.app_stats_onprem.user_id"];
+ created_at?: parameters["rowFilter.app_stats_onprem.created_at"];
+ updated_at?: parameters["rowFilter.app_stats_onprem.updated_at"];
+ channels?: parameters["rowFilter.app_stats_onprem.channels"];
+ mlu?: parameters["rowFilter.app_stats_onprem.mlu"];
+ versions?: parameters["rowFilter.app_stats_onprem.versions"];
+ shared?: parameters["rowFilter.app_stats_onprem.shared"];
+ mlu_real?: parameters["rowFilter.app_stats_onprem.mlu_real"];
+ };
+ body: {
+ /** app_stats_onprem */
+ app_stats_onprem?: definitions["app_stats_onprem"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/app_versions": {
+ get: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.app_versions.id"];
+ created_at?: parameters["rowFilter.app_versions.created_at"];
+ app_id?: parameters["rowFilter.app_versions.app_id"];
+ name?: parameters["rowFilter.app_versions.name"];
+ bucket_id?: parameters["rowFilter.app_versions.bucket_id"];
+ user_id?: parameters["rowFilter.app_versions.user_id"];
+ updated_at?: parameters["rowFilter.app_versions.updated_at"];
+ deleted?: parameters["rowFilter.app_versions.deleted"];
+ external_url?: parameters["rowFilter.app_versions.external_url"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["app_versions"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** app_versions */
+ app_versions?: definitions["app_versions"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.app_versions.id"];
+ created_at?: parameters["rowFilter.app_versions.created_at"];
+ app_id?: parameters["rowFilter.app_versions.app_id"];
+ name?: parameters["rowFilter.app_versions.name"];
+ bucket_id?: parameters["rowFilter.app_versions.bucket_id"];
+ user_id?: parameters["rowFilter.app_versions.user_id"];
+ updated_at?: parameters["rowFilter.app_versions.updated_at"];
+ deleted?: parameters["rowFilter.app_versions.deleted"];
+ external_url?: parameters["rowFilter.app_versions.external_url"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.app_versions.id"];
+ created_at?: parameters["rowFilter.app_versions.created_at"];
+ app_id?: parameters["rowFilter.app_versions.app_id"];
+ name?: parameters["rowFilter.app_versions.name"];
+ bucket_id?: parameters["rowFilter.app_versions.bucket_id"];
+ user_id?: parameters["rowFilter.app_versions.user_id"];
+ updated_at?: parameters["rowFilter.app_versions.updated_at"];
+ deleted?: parameters["rowFilter.app_versions.deleted"];
+ external_url?: parameters["rowFilter.app_versions.external_url"];
+ };
+ body: {
+ /** app_versions */
+ app_versions?: definitions["app_versions"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/apps": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.apps.created_at"];
+ app_id?: parameters["rowFilter.apps.app_id"];
+ icon_url?: parameters["rowFilter.apps.icon_url"];
+ user_id?: parameters["rowFilter.apps.user_id"];
+ name?: parameters["rowFilter.apps.name"];
+ last_version?: parameters["rowFilter.apps.last_version"];
+ updated_at?: parameters["rowFilter.apps.updated_at"];
+ id?: parameters["rowFilter.apps.id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["apps"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** apps */
+ apps?: definitions["apps"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.apps.created_at"];
+ app_id?: parameters["rowFilter.apps.app_id"];
+ icon_url?: parameters["rowFilter.apps.icon_url"];
+ user_id?: parameters["rowFilter.apps.user_id"];
+ name?: parameters["rowFilter.apps.name"];
+ last_version?: parameters["rowFilter.apps.last_version"];
+ updated_at?: parameters["rowFilter.apps.updated_at"];
+ id?: parameters["rowFilter.apps.id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.apps.created_at"];
+ app_id?: parameters["rowFilter.apps.app_id"];
+ icon_url?: parameters["rowFilter.apps.icon_url"];
+ user_id?: parameters["rowFilter.apps.user_id"];
+ name?: parameters["rowFilter.apps.name"];
+ last_version?: parameters["rowFilter.apps.last_version"];
+ updated_at?: parameters["rowFilter.apps.updated_at"];
+ id?: parameters["rowFilter.apps.id"];
+ };
+ body: {
+ /** apps */
+ apps?: definitions["apps"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/channel_devices": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.channel_devices.created_at"];
+ channel_id?: parameters["rowFilter.channel_devices.channel_id"];
+ app_id?: parameters["rowFilter.channel_devices.app_id"];
+ updated_at?: parameters["rowFilter.channel_devices.updated_at"];
+ created_by?: parameters["rowFilter.channel_devices.created_by"];
+ device_id?: parameters["rowFilter.channel_devices.device_id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["channel_devices"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** channel_devices */
+ channel_devices?: definitions["channel_devices"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.channel_devices.created_at"];
+ channel_id?: parameters["rowFilter.channel_devices.channel_id"];
+ app_id?: parameters["rowFilter.channel_devices.app_id"];
+ updated_at?: parameters["rowFilter.channel_devices.updated_at"];
+ created_by?: parameters["rowFilter.channel_devices.created_by"];
+ device_id?: parameters["rowFilter.channel_devices.device_id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.channel_devices.created_at"];
+ channel_id?: parameters["rowFilter.channel_devices.channel_id"];
+ app_id?: parameters["rowFilter.channel_devices.app_id"];
+ updated_at?: parameters["rowFilter.channel_devices.updated_at"];
+ created_by?: parameters["rowFilter.channel_devices.created_by"];
+ device_id?: parameters["rowFilter.channel_devices.device_id"];
+ };
+ body: {
+ /** channel_devices */
+ channel_devices?: definitions["channel_devices"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/channel_users": {
+ get: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.channel_users.id"];
+ created_at?: parameters["rowFilter.channel_users.created_at"];
+ user_id?: parameters["rowFilter.channel_users.user_id"];
+ channel_id?: parameters["rowFilter.channel_users.channel_id"];
+ app_id?: parameters["rowFilter.channel_users.app_id"];
+ updated_at?: parameters["rowFilter.channel_users.updated_at"];
+ created_by?: parameters["rowFilter.channel_users.created_by"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["channel_users"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** channel_users */
+ channel_users?: definitions["channel_users"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.channel_users.id"];
+ created_at?: parameters["rowFilter.channel_users.created_at"];
+ user_id?: parameters["rowFilter.channel_users.user_id"];
+ channel_id?: parameters["rowFilter.channel_users.channel_id"];
+ app_id?: parameters["rowFilter.channel_users.app_id"];
+ updated_at?: parameters["rowFilter.channel_users.updated_at"];
+ created_by?: parameters["rowFilter.channel_users.created_by"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.channel_users.id"];
+ created_at?: parameters["rowFilter.channel_users.created_at"];
+ user_id?: parameters["rowFilter.channel_users.user_id"];
+ channel_id?: parameters["rowFilter.channel_users.channel_id"];
+ app_id?: parameters["rowFilter.channel_users.app_id"];
+ updated_at?: parameters["rowFilter.channel_users.updated_at"];
+ created_by?: parameters["rowFilter.channel_users.created_by"];
+ };
+ body: {
+ /** channel_users */
+ channel_users?: definitions["channel_users"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/channels": {
+ get: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.channels.id"];
+ created_at?: parameters["rowFilter.channels.created_at"];
+ name?: parameters["rowFilter.channels.name"];
+ app_id?: parameters["rowFilter.channels.app_id"];
+ version?: parameters["rowFilter.channels.version"];
+ created_by?: parameters["rowFilter.channels.created_by"];
+ updated_at?: parameters["rowFilter.channels.updated_at"];
+ public?: parameters["rowFilter.channels.public"];
+ disableAutoUpdateUnderNative?: parameters["rowFilter.channels.disableAutoUpdateUnderNative"];
+ disableAutoUpdateToMajor?: parameters["rowFilter.channels.disableAutoUpdateToMajor"];
+ beta?: parameters["rowFilter.channels.beta"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["channels"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** channels */
+ channels?: definitions["channels"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.channels.id"];
+ created_at?: parameters["rowFilter.channels.created_at"];
+ name?: parameters["rowFilter.channels.name"];
+ app_id?: parameters["rowFilter.channels.app_id"];
+ version?: parameters["rowFilter.channels.version"];
+ created_by?: parameters["rowFilter.channels.created_by"];
+ updated_at?: parameters["rowFilter.channels.updated_at"];
+ public?: parameters["rowFilter.channels.public"];
+ disableAutoUpdateUnderNative?: parameters["rowFilter.channels.disableAutoUpdateUnderNative"];
+ disableAutoUpdateToMajor?: parameters["rowFilter.channels.disableAutoUpdateToMajor"];
+ beta?: parameters["rowFilter.channels.beta"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.channels.id"];
+ created_at?: parameters["rowFilter.channels.created_at"];
+ name?: parameters["rowFilter.channels.name"];
+ app_id?: parameters["rowFilter.channels.app_id"];
+ version?: parameters["rowFilter.channels.version"];
+ created_by?: parameters["rowFilter.channels.created_by"];
+ updated_at?: parameters["rowFilter.channels.updated_at"];
+ public?: parameters["rowFilter.channels.public"];
+ disableAutoUpdateUnderNative?: parameters["rowFilter.channels.disableAutoUpdateUnderNative"];
+ disableAutoUpdateToMajor?: parameters["rowFilter.channels.disableAutoUpdateToMajor"];
+ beta?: parameters["rowFilter.channels.beta"];
+ };
+ body: {
+ /** channels */
+ channels?: definitions["channels"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/devices": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices.created_at"];
+ updated_at?: parameters["rowFilter.devices.updated_at"];
+ device_id?: parameters["rowFilter.devices.device_id"];
+ version?: parameters["rowFilter.devices.version"];
+ app_id?: parameters["rowFilter.devices.app_id"];
+ platform?: parameters["rowFilter.devices.platform"];
+ plugin_version?: parameters["rowFilter.devices.plugin_version"];
+ os_version?: parameters["rowFilter.devices.os_version"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["devices"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** devices */
+ devices?: definitions["devices"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices.created_at"];
+ updated_at?: parameters["rowFilter.devices.updated_at"];
+ device_id?: parameters["rowFilter.devices.device_id"];
+ version?: parameters["rowFilter.devices.version"];
+ app_id?: parameters["rowFilter.devices.app_id"];
+ platform?: parameters["rowFilter.devices.platform"];
+ plugin_version?: parameters["rowFilter.devices.plugin_version"];
+ os_version?: parameters["rowFilter.devices.os_version"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices.created_at"];
+ updated_at?: parameters["rowFilter.devices.updated_at"];
+ device_id?: parameters["rowFilter.devices.device_id"];
+ version?: parameters["rowFilter.devices.version"];
+ app_id?: parameters["rowFilter.devices.app_id"];
+ platform?: parameters["rowFilter.devices.platform"];
+ plugin_version?: parameters["rowFilter.devices.plugin_version"];
+ os_version?: parameters["rowFilter.devices.os_version"];
+ };
+ body: {
+ /** devices */
+ devices?: definitions["devices"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/devices_onprem": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices_onprem.created_at"];
+ updated_at?: parameters["rowFilter.devices_onprem.updated_at"];
+ platform?: parameters["rowFilter.devices_onprem.platform"];
+ plugin_version?: parameters["rowFilter.devices_onprem.plugin_version"];
+ version?: parameters["rowFilter.devices_onprem.version"];
+ app_id?: parameters["rowFilter.devices_onprem.app_id"];
+ device_id?: parameters["rowFilter.devices_onprem.device_id"];
+ os_version?: parameters["rowFilter.devices_onprem.os_version"];
+ id?: parameters["rowFilter.devices_onprem.id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["devices_onprem"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** devices_onprem */
+ devices_onprem?: definitions["devices_onprem"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices_onprem.created_at"];
+ updated_at?: parameters["rowFilter.devices_onprem.updated_at"];
+ platform?: parameters["rowFilter.devices_onprem.platform"];
+ plugin_version?: parameters["rowFilter.devices_onprem.plugin_version"];
+ version?: parameters["rowFilter.devices_onprem.version"];
+ app_id?: parameters["rowFilter.devices_onprem.app_id"];
+ device_id?: parameters["rowFilter.devices_onprem.device_id"];
+ os_version?: parameters["rowFilter.devices_onprem.os_version"];
+ id?: parameters["rowFilter.devices_onprem.id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices_onprem.created_at"];
+ updated_at?: parameters["rowFilter.devices_onprem.updated_at"];
+ platform?: parameters["rowFilter.devices_onprem.platform"];
+ plugin_version?: parameters["rowFilter.devices_onprem.plugin_version"];
+ version?: parameters["rowFilter.devices_onprem.version"];
+ app_id?: parameters["rowFilter.devices_onprem.app_id"];
+ device_id?: parameters["rowFilter.devices_onprem.device_id"];
+ os_version?: parameters["rowFilter.devices_onprem.os_version"];
+ id?: parameters["rowFilter.devices_onprem.id"];
+ };
+ body: {
+ /** devices_onprem */
+ devices_onprem?: definitions["devices_onprem"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/devices_override": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices_override.created_at"];
+ updated_at?: parameters["rowFilter.devices_override.updated_at"];
+ device_id?: parameters["rowFilter.devices_override.device_id"];
+ version?: parameters["rowFilter.devices_override.version"];
+ app_id?: parameters["rowFilter.devices_override.app_id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["devices_override"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** devices_override */
+ devices_override?: definitions["devices_override"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices_override.created_at"];
+ updated_at?: parameters["rowFilter.devices_override.updated_at"];
+ device_id?: parameters["rowFilter.devices_override.device_id"];
+ version?: parameters["rowFilter.devices_override.version"];
+ app_id?: parameters["rowFilter.devices_override.app_id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.devices_override.created_at"];
+ updated_at?: parameters["rowFilter.devices_override.updated_at"];
+ device_id?: parameters["rowFilter.devices_override.device_id"];
+ version?: parameters["rowFilter.devices_override.version"];
+ app_id?: parameters["rowFilter.devices_override.app_id"];
+ };
+ body: {
+ /** devices_override */
+ devices_override?: definitions["devices_override"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/stats": {
+ get: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.stats.id"];
+ created_at?: parameters["rowFilter.stats.created_at"];
+ platform?: parameters["rowFilter.stats.platform"];
+ action?: parameters["rowFilter.stats.action"];
+ device_id?: parameters["rowFilter.stats.device_id"];
+ version_build?: parameters["rowFilter.stats.version_build"];
+ version?: parameters["rowFilter.stats.version"];
+ app_id?: parameters["rowFilter.stats.app_id"];
+ updated_at?: parameters["rowFilter.stats.updated_at"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["stats"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** stats */
+ stats?: definitions["stats"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.stats.id"];
+ created_at?: parameters["rowFilter.stats.created_at"];
+ platform?: parameters["rowFilter.stats.platform"];
+ action?: parameters["rowFilter.stats.action"];
+ device_id?: parameters["rowFilter.stats.device_id"];
+ version_build?: parameters["rowFilter.stats.version_build"];
+ version?: parameters["rowFilter.stats.version"];
+ app_id?: parameters["rowFilter.stats.app_id"];
+ updated_at?: parameters["rowFilter.stats.updated_at"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.stats.id"];
+ created_at?: parameters["rowFilter.stats.created_at"];
+ platform?: parameters["rowFilter.stats.platform"];
+ action?: parameters["rowFilter.stats.action"];
+ device_id?: parameters["rowFilter.stats.device_id"];
+ version_build?: parameters["rowFilter.stats.version_build"];
+ version?: parameters["rowFilter.stats.version"];
+ app_id?: parameters["rowFilter.stats.app_id"];
+ updated_at?: parameters["rowFilter.stats.updated_at"];
+ };
+ body: {
+ /** stats */
+ stats?: definitions["stats"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/stats_onprem": {
+ get: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.stats_onprem.id"];
+ created_at?: parameters["rowFilter.stats_onprem.created_at"];
+ platform?: parameters["rowFilter.stats_onprem.platform"];
+ action?: parameters["rowFilter.stats_onprem.action"];
+ device_id?: parameters["rowFilter.stats_onprem.device_id"];
+ version_build?: parameters["rowFilter.stats_onprem.version_build"];
+ app_id?: parameters["rowFilter.stats_onprem.app_id"];
+ updated_at?: parameters["rowFilter.stats_onprem.updated_at"];
+ version?: parameters["rowFilter.stats_onprem.version"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["stats_onprem"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** stats_onprem */
+ stats_onprem?: definitions["stats_onprem"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.stats_onprem.id"];
+ created_at?: parameters["rowFilter.stats_onprem.created_at"];
+ platform?: parameters["rowFilter.stats_onprem.platform"];
+ action?: parameters["rowFilter.stats_onprem.action"];
+ device_id?: parameters["rowFilter.stats_onprem.device_id"];
+ version_build?: parameters["rowFilter.stats_onprem.version_build"];
+ app_id?: parameters["rowFilter.stats_onprem.app_id"];
+ updated_at?: parameters["rowFilter.stats_onprem.updated_at"];
+ version?: parameters["rowFilter.stats_onprem.version"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ id?: parameters["rowFilter.stats_onprem.id"];
+ created_at?: parameters["rowFilter.stats_onprem.created_at"];
+ platform?: parameters["rowFilter.stats_onprem.platform"];
+ action?: parameters["rowFilter.stats_onprem.action"];
+ device_id?: parameters["rowFilter.stats_onprem.device_id"];
+ version_build?: parameters["rowFilter.stats_onprem.version_build"];
+ app_id?: parameters["rowFilter.stats_onprem.app_id"];
+ updated_at?: parameters["rowFilter.stats_onprem.updated_at"];
+ version?: parameters["rowFilter.stats_onprem.version"];
+ };
+ body: {
+ /** stats_onprem */
+ stats_onprem?: definitions["stats_onprem"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/stripe_info": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.stripe_info.created_at"];
+ updated_at?: parameters["rowFilter.stripe_info.updated_at"];
+ subscription_id?: parameters["rowFilter.stripe_info.subscription_id"];
+ customer_id?: parameters["rowFilter.stripe_info.customer_id"];
+ status?: parameters["rowFilter.stripe_info.status"];
+ product_id?: parameters["rowFilter.stripe_info.product_id"];
+ trial_at?: parameters["rowFilter.stripe_info.trial_at"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["stripe_info"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** stripe_info */
+ stripe_info?: definitions["stripe_info"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.stripe_info.created_at"];
+ updated_at?: parameters["rowFilter.stripe_info.updated_at"];
+ subscription_id?: parameters["rowFilter.stripe_info.subscription_id"];
+ customer_id?: parameters["rowFilter.stripe_info.customer_id"];
+ status?: parameters["rowFilter.stripe_info.status"];
+ product_id?: parameters["rowFilter.stripe_info.product_id"];
+ trial_at?: parameters["rowFilter.stripe_info.trial_at"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.stripe_info.created_at"];
+ updated_at?: parameters["rowFilter.stripe_info.updated_at"];
+ subscription_id?: parameters["rowFilter.stripe_info.subscription_id"];
+ customer_id?: parameters["rowFilter.stripe_info.customer_id"];
+ status?: parameters["rowFilter.stripe_info.status"];
+ product_id?: parameters["rowFilter.stripe_info.product_id"];
+ trial_at?: parameters["rowFilter.stripe_info.trial_at"];
+ };
+ body: {
+ /** stripe_info */
+ stripe_info?: definitions["stripe_info"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/users": {
+ get: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.users.created_at"];
+ image_url?: parameters["rowFilter.users.image_url"];
+ first_name?: parameters["rowFilter.users.first_name"];
+ last_name?: parameters["rowFilter.users.last_name"];
+ country?: parameters["rowFilter.users.country"];
+ email?: parameters["rowFilter.users.email"];
+ id?: parameters["rowFilter.users.id"];
+ updated_at?: parameters["rowFilter.users.updated_at"];
+ enableNotifications?: parameters["rowFilter.users.enableNotifications"];
+ optForNewsletters?: parameters["rowFilter.users.optForNewsletters"];
+ legalAccepted?: parameters["rowFilter.users.legalAccepted"];
+ customer_id?: parameters["rowFilter.users.customer_id"];
+ /** Filtering Columns */
+ select?: parameters["select"];
+ /** Ordering */
+ order?: parameters["order"];
+ /** Limiting and Pagination */
+ offset?: parameters["offset"];
+ /** Limiting and Pagination */
+ limit?: parameters["limit"];
+ };
+ header: {
+ /** Limiting and Pagination */
+ Range?: parameters["range"];
+ /** Limiting and Pagination */
+ "Range-Unit"?: parameters["rangeUnit"];
+ /** Preference */
+ Prefer?: parameters["preferCount"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: {
+ schema: definitions["users"][];
+ };
+ /** Partial Content */
+ 206: unknown;
+ };
+ };
+ post: {
+ parameters: {
+ body: {
+ /** users */
+ users?: definitions["users"];
+ };
+ query: {
+ /** Filtering Columns */
+ select?: parameters["select"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** Created */
+ 201: unknown;
+ };
+ };
+ delete: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.users.created_at"];
+ image_url?: parameters["rowFilter.users.image_url"];
+ first_name?: parameters["rowFilter.users.first_name"];
+ last_name?: parameters["rowFilter.users.last_name"];
+ country?: parameters["rowFilter.users.country"];
+ email?: parameters["rowFilter.users.email"];
+ id?: parameters["rowFilter.users.id"];
+ updated_at?: parameters["rowFilter.users.updated_at"];
+ enableNotifications?: parameters["rowFilter.users.enableNotifications"];
+ optForNewsletters?: parameters["rowFilter.users.optForNewsletters"];
+ legalAccepted?: parameters["rowFilter.users.legalAccepted"];
+ customer_id?: parameters["rowFilter.users.customer_id"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ patch: {
+ parameters: {
+ query: {
+ created_at?: parameters["rowFilter.users.created_at"];
+ image_url?: parameters["rowFilter.users.image_url"];
+ first_name?: parameters["rowFilter.users.first_name"];
+ last_name?: parameters["rowFilter.users.last_name"];
+ country?: parameters["rowFilter.users.country"];
+ email?: parameters["rowFilter.users.email"];
+ id?: parameters["rowFilter.users.id"];
+ updated_at?: parameters["rowFilter.users.updated_at"];
+ enableNotifications?: parameters["rowFilter.users.enableNotifications"];
+ optForNewsletters?: parameters["rowFilter.users.optForNewsletters"];
+ legalAccepted?: parameters["rowFilter.users.legalAccepted"];
+ customer_id?: parameters["rowFilter.users.customer_id"];
+ };
+ body: {
+ /** users */
+ users?: definitions["users"];
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferReturn"];
+ };
+ };
+ responses: {
+ /** No Content */
+ 204: never;
+ };
+ };
+ };
+ "/rpc/is_app_owner": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: character varying */
+ appid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/get_max_channel": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/get_dl_by_month_by_app": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: integer */
+ pastmonth: number;
+ /** Format: character varying */
+ appid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/is_app_shared": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: character varying */
+ appid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/get_max_shared": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/get_max_version": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/is_version_shared": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: bigint */
+ versionid: number;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+ "/rpc/get_dl_by_month": {
+ post: {
+ parameters: {
+ body: {
+ args: {
+ /** Format: uuid */
+ userid: string;
+ /** Format: integer */
+ pastmonth: number;
+ };
+ };
+ header: {
+ /** Preference */
+ Prefer?: parameters["preferParams"];
+ };
+ };
+ responses: {
+ /** OK */
+ 200: unknown;
+ };
+ };
+ };
+}
+
+export interface definitions {
+ apikeys: {
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: number;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /** Format: uuid */
+ user_id: string;
+ /** Format: character varying */
+ key: string;
+ /**
+ * Format: public.key_mode
+ * @enum {string}
+ */
+ mode: "read" | "write" | "all" | "upload";
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ };
+ app_stats: {
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /** Format: uuid */
+ user_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: smallint */
+ channels: number;
+ /** Format: bigint */
+ mlu: number;
+ /** Format: bigint */
+ versions: number;
+ /** Format: bigint */
+ shared: number;
+ /** Format: bigint */
+ mlu_real: number;
+ /** Format: bigint */
+ devices: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ * @default 2022-05
+ */
+ date_id: string;
+ };
+ app_stats_onprem: {
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /** Format: uuid */
+ user_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: smallint */
+ channels?: number;
+ /** Format: bigint */
+ mlu?: number;
+ /** Format: bigint */
+ versions?: number;
+ /** Format: bigint */
+ shared?: number;
+ /** Format: bigint */
+ mlu_real?: number;
+ };
+ app_versions: {
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: number;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /** Format: character varying */
+ name: string;
+ /** Format: character varying */
+ bucket_id?: string;
+ /** Format: uuid */
+ user_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: boolean */
+ deleted: boolean;
+ /** Format: character varying */
+ external_url?: string;
+ };
+ apps: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ */
+ app_id: string;
+ /** Format: character varying */
+ icon_url: string;
+ /** Format: uuid */
+ user_id: string;
+ /** Format: character varying */
+ name?: string;
+ /** Format: character varying */
+ last_version?: string;
+ /** Format: timestamp with time zone */
+ updated_at?: string;
+ /**
+ * Format: uuid
+ * @default extensions.uuid_generate_v4()
+ */
+ id?: string;
+ };
+ channel_devices: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Foreign Key to `channels.id`.
+ */
+ channel_id: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at: string;
+ /**
+ * Format: uuid
+ * @description Note:
+ * This is a Foreign Key to `users.id`.
+ */
+ created_by?: string;
+ /**
+ * Format: text
+ * @description Note:
+ * This is a Primary Key.
+ * This is a Foreign Key to `devices.device_id`.
+ */
+ device_id: string;
+ };
+ channel_users: {
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: number;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: uuid
+ * @description Note:
+ * This is a Foreign Key to `users.id`.
+ */
+ user_id: string;
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Foreign Key to `channels.id`.
+ */
+ channel_id: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at: string;
+ /**
+ * Format: uuid
+ * @description Note:
+ * This is a Foreign Key to `users.id`.
+ */
+ created_by?: string;
+ };
+ channels: {
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: number;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at: string;
+ /** Format: character varying */
+ name: string;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Foreign Key to `app_versions.id`.
+ */
+ version: number;
+ /**
+ * Format: uuid
+ * @description Note:
+ * This is a Foreign Key to `users.id`.
+ */
+ created_by: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at: string;
+ /** Format: boolean */
+ public: boolean;
+ /**
+ * Format: boolean
+ * @default true
+ */
+ disableAutoUpdateUnderNative: boolean;
+ /**
+ * Format: boolean
+ * @default true
+ */
+ disableAutoUpdateToMajor: boolean;
+ /** Format: boolean */
+ beta?: boolean;
+ };
+ devices: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /**
+ * Format: text
+ * @description Note:
+ * This is a Primary Key.
+ */
+ device_id: string;
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Foreign Key to `app_versions.id`.
+ */
+ version: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /**
+ * Format: public.platform_os
+ * @enum {string}
+ */
+ platform?: "ios" | "android";
+ /**
+ * Format: text
+ * @default 2.3.3
+ */
+ plugin_version: string;
+ /** Format: character varying */
+ os_version?: string;
+ };
+ devices_onprem: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /**
+ * Format: public.platform_os
+ * @enum {string}
+ */
+ platform?: "ios" | "android";
+ /**
+ * Format: text
+ * @default 2.3.3
+ */
+ plugin_version: string;
+ /** Format: character varying */
+ version?: string;
+ /** Format: character varying */
+ app_id?: string;
+ /** Format: character varying */
+ device_id?: string;
+ /** Format: character varying */
+ os_version?: string;
+ /**
+ * Format: uuid
+ * @description Note:
+ * This is a Primary Key.
+ * @default extensions.uuid_generate_v4()
+ */
+ id: string;
+ };
+ devices_override: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /**
+ * Format: text
+ * @description Note:
+ * This is a Primary Key.
+ * This is a Foreign Key to `devices.device_id`.
+ */
+ device_id: string;
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Foreign Key to `app_versions.id`.
+ */
+ version: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ };
+ stats: {
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: number;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: public.platform_os
+ * @enum {string}
+ */
+ platform: "ios" | "android";
+ /** Format: text */
+ action: string;
+ /**
+ * Format: text
+ * @description Note:
+ * This is a Foreign Key to `devices.device_id`.
+ */
+ device_id: string;
+ /** Format: text */
+ version_build: string;
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Foreign Key to `app_versions.id`.
+ */
+ version: number;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Foreign Key to `apps.app_id`.
+ */
+ app_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ };
+ stats_onprem: {
+ /**
+ * Format: bigint
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: number;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /**
+ * Format: public.platform_os
+ * @enum {string}
+ */
+ platform: "ios" | "android";
+ /** Format: text */
+ action: string;
+ /** Format: character varying */
+ device_id: string;
+ /** Format: text */
+ version_build: string;
+ /** Format: character varying */
+ app_id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: character varying */
+ version: string;
+ };
+ stripe_info: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at: string;
+ /** Format: character varying */
+ subscription_id?: string;
+ /**
+ * Format: character varying
+ * @description Note:
+ * This is a Primary Key.
+ */
+ customer_id: string;
+ /**
+ * Format: public.stripe_status
+ * @enum {string}
+ */
+ status?:
+ | "created"
+ | "succeeded"
+ | "updated"
+ | "failed"
+ | "deleted"
+ | "canceled";
+ /** Format: character varying */
+ product_id?: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ trial_at: string;
+ };
+ users: {
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ created_at?: string;
+ /** Format: character varying */
+ image_url?: string;
+ /** Format: character varying */
+ first_name?: string;
+ /** Format: character varying */
+ last_name?: string;
+ /** Format: character varying */
+ country?: string;
+ /** Format: character varying */
+ email: string;
+ /**
+ * Format: uuid
+ * @description Note:
+ * This is a Primary Key.
+ */
+ id: string;
+ /**
+ * Format: timestamp with time zone
+ * @default now()
+ */
+ updated_at?: string;
+ /** Format: boolean */
+ enableNotifications: boolean;
+ /** Format: boolean */
+ optForNewsletters: boolean;
+ /** Format: boolean */
+ legalAccepted: boolean;
+ /** Format: character varying */
+ customer_id?: string;
+ };
+}
+
+export interface parameters {
+ /**
+ * @description Preference
+ * @enum {string}
+ */
+ preferParams: "params=single-object";
+ /**
+ * @description Preference
+ * @enum {string}
+ */
+ preferReturn: "return=representation" | "return=minimal" | "return=none";
+ /**
+ * @description Preference
+ * @enum {string}
+ */
+ preferCount: "count=none";
+ /** @description Filtering Columns */
+ select: string;
+ /** @description On Conflict */
+ on_conflict: string;
+ /** @description Ordering */
+ order: string;
+ /** @description Limiting and Pagination */
+ range: string;
+ /**
+ * @description Limiting and Pagination
+ * @default items
+ */
+ rangeUnit: string;
+ /** @description Limiting and Pagination */
+ offset: string;
+ /** @description Limiting and Pagination */
+ limit: string;
+ /** @description apikeys */
+ "body.apikeys": definitions["apikeys"];
+ /** Format: bigint */
+ "rowFilter.apikeys.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.apikeys.created_at": string;
+ /** Format: uuid */
+ "rowFilter.apikeys.user_id": string;
+ /** Format: character varying */
+ "rowFilter.apikeys.key": string;
+ /** Format: public.key_mode */
+ "rowFilter.apikeys.mode": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.apikeys.updated_at": string;
+ /** @description app_stats */
+ "body.app_stats": definitions["app_stats"];
+ /** Format: character varying */
+ "rowFilter.app_stats.app_id": string;
+ /** Format: uuid */
+ "rowFilter.app_stats.user_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats.updated_at": string;
+ /** Format: smallint */
+ "rowFilter.app_stats.channels": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.mlu": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.versions": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.shared": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.mlu_real": string;
+ /** Format: bigint */
+ "rowFilter.app_stats.devices": string;
+ /** Format: character varying */
+ "rowFilter.app_stats.date_id": string;
+ /** @description app_stats_onprem */
+ "body.app_stats_onprem": definitions["app_stats_onprem"];
+ /** Format: character varying */
+ "rowFilter.app_stats_onprem.app_id": string;
+ /** Format: uuid */
+ "rowFilter.app_stats_onprem.user_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats_onprem.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_stats_onprem.updated_at": string;
+ /** Format: smallint */
+ "rowFilter.app_stats_onprem.channels": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.mlu": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.versions": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.shared": string;
+ /** Format: bigint */
+ "rowFilter.app_stats_onprem.mlu_real": string;
+ /** @description app_versions */
+ "body.app_versions": definitions["app_versions"];
+ /** Format: bigint */
+ "rowFilter.app_versions.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_versions.created_at": string;
+ /** Format: character varying */
+ "rowFilter.app_versions.app_id": string;
+ /** Format: character varying */
+ "rowFilter.app_versions.name": string;
+ /** Format: character varying */
+ "rowFilter.app_versions.bucket_id": string;
+ /** Format: uuid */
+ "rowFilter.app_versions.user_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.app_versions.updated_at": string;
+ /** Format: boolean */
+ "rowFilter.app_versions.deleted": string;
+ /** Format: character varying */
+ "rowFilter.app_versions.external_url": string;
+ /** @description apps */
+ "body.apps": definitions["apps"];
+ /** Format: timestamp with time zone */
+ "rowFilter.apps.created_at": string;
+ /** Format: character varying */
+ "rowFilter.apps.app_id": string;
+ /** Format: character varying */
+ "rowFilter.apps.icon_url": string;
+ /** Format: uuid */
+ "rowFilter.apps.user_id": string;
+ /** Format: character varying */
+ "rowFilter.apps.name": string;
+ /** Format: character varying */
+ "rowFilter.apps.last_version": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.apps.updated_at": string;
+ /** Format: uuid */
+ "rowFilter.apps.id": string;
+ /** @description channel_devices */
+ "body.channel_devices": definitions["channel_devices"];
+ /** Format: timestamp with time zone */
+ "rowFilter.channel_devices.created_at": string;
+ /** Format: bigint */
+ "rowFilter.channel_devices.channel_id": string;
+ /** Format: character varying */
+ "rowFilter.channel_devices.app_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.channel_devices.updated_at": string;
+ /** Format: uuid */
+ "rowFilter.channel_devices.created_by": string;
+ /** Format: text */
+ "rowFilter.channel_devices.device_id": string;
+ /** @description channel_users */
+ "body.channel_users": definitions["channel_users"];
+ /** Format: bigint */
+ "rowFilter.channel_users.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.channel_users.created_at": string;
+ /** Format: uuid */
+ "rowFilter.channel_users.user_id": string;
+ /** Format: bigint */
+ "rowFilter.channel_users.channel_id": string;
+ /** Format: character varying */
+ "rowFilter.channel_users.app_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.channel_users.updated_at": string;
+ /** Format: uuid */
+ "rowFilter.channel_users.created_by": string;
+ /** @description channels */
+ "body.channels": definitions["channels"];
+ /** Format: bigint */
+ "rowFilter.channels.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.channels.created_at": string;
+ /** Format: character varying */
+ "rowFilter.channels.name": string;
+ /** Format: character varying */
+ "rowFilter.channels.app_id": string;
+ /** Format: bigint */
+ "rowFilter.channels.version": string;
+ /** Format: uuid */
+ "rowFilter.channels.created_by": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.channels.updated_at": string;
+ /** Format: boolean */
+ "rowFilter.channels.public": string;
+ /** Format: boolean */
+ "rowFilter.channels.disableAutoUpdateUnderNative": string;
+ /** Format: boolean */
+ "rowFilter.channels.disableAutoUpdateToMajor": string;
+ /** Format: boolean */
+ "rowFilter.channels.beta": string;
+ /** @description devices */
+ "body.devices": definitions["devices"];
+ /** Format: timestamp with time zone */
+ "rowFilter.devices.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.devices.updated_at": string;
+ /** Format: text */
+ "rowFilter.devices.device_id": string;
+ /** Format: bigint */
+ "rowFilter.devices.version": string;
+ /** Format: character varying */
+ "rowFilter.devices.app_id": string;
+ /** Format: public.platform_os */
+ "rowFilter.devices.platform": string;
+ /** Format: text */
+ "rowFilter.devices.plugin_version": string;
+ /** Format: character varying */
+ "rowFilter.devices.os_version": string;
+ /** @description devices_onprem */
+ "body.devices_onprem": definitions["devices_onprem"];
+ /** Format: timestamp with time zone */
+ "rowFilter.devices_onprem.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.devices_onprem.updated_at": string;
+ /** Format: public.platform_os */
+ "rowFilter.devices_onprem.platform": string;
+ /** Format: text */
+ "rowFilter.devices_onprem.plugin_version": string;
+ /** Format: character varying */
+ "rowFilter.devices_onprem.version": string;
+ /** Format: character varying */
+ "rowFilter.devices_onprem.app_id": string;
+ /** Format: character varying */
+ "rowFilter.devices_onprem.device_id": string;
+ /** Format: character varying */
+ "rowFilter.devices_onprem.os_version": string;
+ /** Format: uuid */
+ "rowFilter.devices_onprem.id": string;
+ /** @description devices_override */
+ "body.devices_override": definitions["devices_override"];
+ /** Format: timestamp with time zone */
+ "rowFilter.devices_override.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.devices_override.updated_at": string;
+ /** Format: text */
+ "rowFilter.devices_override.device_id": string;
+ /** Format: bigint */
+ "rowFilter.devices_override.version": string;
+ /** Format: character varying */
+ "rowFilter.devices_override.app_id": string;
+ /** @description stats */
+ "body.stats": definitions["stats"];
+ /** Format: bigint */
+ "rowFilter.stats.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stats.created_at": string;
+ /** Format: public.platform_os */
+ "rowFilter.stats.platform": string;
+ /** Format: text */
+ "rowFilter.stats.action": string;
+ /** Format: text */
+ "rowFilter.stats.device_id": string;
+ /** Format: text */
+ "rowFilter.stats.version_build": string;
+ /** Format: bigint */
+ "rowFilter.stats.version": string;
+ /** Format: character varying */
+ "rowFilter.stats.app_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stats.updated_at": string;
+ /** @description stats_onprem */
+ "body.stats_onprem": definitions["stats_onprem"];
+ /** Format: bigint */
+ "rowFilter.stats_onprem.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stats_onprem.created_at": string;
+ /** Format: public.platform_os */
+ "rowFilter.stats_onprem.platform": string;
+ /** Format: text */
+ "rowFilter.stats_onprem.action": string;
+ /** Format: character varying */
+ "rowFilter.stats_onprem.device_id": string;
+ /** Format: text */
+ "rowFilter.stats_onprem.version_build": string;
+ /** Format: character varying */
+ "rowFilter.stats_onprem.app_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stats_onprem.updated_at": string;
+ /** Format: character varying */
+ "rowFilter.stats_onprem.version": string;
+ /** @description stripe_info */
+ "body.stripe_info": definitions["stripe_info"];
+ /** Format: timestamp with time zone */
+ "rowFilter.stripe_info.created_at": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stripe_info.updated_at": string;
+ /** Format: character varying */
+ "rowFilter.stripe_info.subscription_id": string;
+ /** Format: character varying */
+ "rowFilter.stripe_info.customer_id": string;
+ /** Format: public.stripe_status */
+ "rowFilter.stripe_info.status": string;
+ /** Format: character varying */
+ "rowFilter.stripe_info.product_id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.stripe_info.trial_at": string;
+ /** @description users */
+ "body.users": definitions["users"];
+ /** Format: timestamp with time zone */
+ "rowFilter.users.created_at": string;
+ /** Format: character varying */
+ "rowFilter.users.image_url": string;
+ /** Format: character varying */
+ "rowFilter.users.first_name": string;
+ /** Format: character varying */
+ "rowFilter.users.last_name": string;
+ /** Format: character varying */
+ "rowFilter.users.country": string;
+ /** Format: character varying */
+ "rowFilter.users.email": string;
+ /** Format: uuid */
+ "rowFilter.users.id": string;
+ /** Format: timestamp with time zone */
+ "rowFilter.users.updated_at": string;
+ /** Format: boolean */
+ "rowFilter.users.enableNotifications": string;
+ /** Format: boolean */
+ "rowFilter.users.optForNewsletters": string;
+ /** Format: boolean */
+ "rowFilter.users.legalAccepted": string;
+ /** Format: character varying */
+ "rowFilter.users.customer_id": string;
+}
+
+export interface operations {}
+
+export interface external {}
diff --git a/supabase/functions/_utils/utils.ts b/supabase/functions/_utils/utils.ts
new file mode 100644
index 0000000000..44f3790d16
--- /dev/null
+++ b/supabase/functions/_utils/utils.ts
@@ -0,0 +1,52 @@
+import type { SupabaseClient } from 'https://esm.sh/@supabase/supabase-js@^1.35.3'
+import type { definitions } from './types_supabase.ts'
+import type { JwtUser } from './types.ts'
+
+export const jwtDecoder = (jwt: string): JwtUser =>
+ JSON.parse(atob(jwt.split('.')[1]))
+
+const basicHeaders = {
+ 'Access-Control-Expose-Headers': 'Content-Length, X-JSON',
+ 'Content-Type': 'application/json',
+}
+
+const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': '*',
+ 'Access-Control-Allow-Methods': 'POST, OPTIONS',
+}
+
+export const checkKey = async(authorization: string | undefined, supabase: SupabaseClient, allowed: definitions['apikeys']['mode'][]): Promise => {
+ if (!authorization)
+ return null
+ try {
+ const { data, error } = await supabase
+ .from('apikeys')
+ .select()
+ .eq('key', authorization)
+ if (!data || !data.length || error || !allowed.includes(data[0].mode))
+ return null
+ return data[0]
+ }
+ catch (error) {
+ console.error(error)
+ return null
+ }
+}
+
+export const sendRes = (data: any = { status: 'ok' }, statusCode = 200) => (new Response(
+ JSON.stringify(data),
+ {
+ status: statusCode,
+ headers: { ...basicHeaders, ...corsHeaders },
+ },
+))
+
+export const sendOptionsRes = () => (new Response(
+ 'ok',
+ {
+ headers: {
+ ...corsHeaders,
+ },
+ },
+))
diff --git a/supabase/functions/add/index.ts b/supabase/functions/add/index.ts
new file mode 100644
index 0000000000..c407317588
--- /dev/null
+++ b/supabase/functions/add/index.ts
@@ -0,0 +1,65 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { Buffer } from 'https://deno.land/x/node_buffer@1.1.0/index.ts'
+// import { isAllowInMyPlan } from '../_utils/plan.ts'
+import { checkAppOwner, supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { checkKey, sendRes } from '../_utils/utils.ts'
+
+interface AppAdd {
+ appid: string
+ name: string
+ icon: string
+ iconType: string
+}
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('apikey')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ const apikey: definitions['apikeys'] | null = await checkKey(authorization, supabase, ['upload', 'all', 'write'])
+ if (!apikey || !event.body)
+ return sendRes({ status: 'Cannot Verify User' }, 400)
+ try {
+ const body = (await event.json()) as AppAdd
+ // if (!(await isAllowInMyPlan(apikey.user_id)))
+ // return sendRes({ status: `Your reached the limit of your plan, upgrade to continue ${Deno.env.get('WEBAPP_URL')}/usage` }, 400)
+
+ if (await checkAppOwner(apikey.user_id, body.appid))
+ return sendRes({ status: 'App exist already' }, 400)
+ const fileName = `icon_${globalThis.crypto.randomUUID()}`
+ let signedURL = 'https://xvwzpoazmxkqosrdewyv.supabase.in/storage/v1/object/public/images/capgo.png'
+ if (body.icon && body.iconType) {
+ const buff = Buffer.from(body.icon, 'base64')
+ const { error } = await supabase.storage
+ .from(`images/${apikey.user_id}/${body.appid}`)
+ .upload(fileName, buff, {
+ contentType: body.iconType,
+ })
+ if (error)
+ return sendRes({ status: 'Cannot Add App', error }, 400)
+ const res = await supabase
+ .storage
+ .from(`images/${apikey.user_id}/${body.appid}`)
+ .getPublicUrl(fileName)
+ signedURL = res.data?.publicURL || signedURL
+ }
+ const { error: dbError } = await supabase
+ .from('apps')
+ .insert({
+ icon_url: signedURL,
+ user_id: apikey.user_id,
+ name: body.name,
+ app_id: body.appid,
+ })
+ if (dbError)
+ return sendRes({ status: 'Cannot Add App', error: JSON.stringify(dbError) }, 400)
+ return sendRes()
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/app_stats/index.ts b/supabase/functions/app_stats/index.ts
new file mode 100644
index 0000000000..717d8c2b0e
--- /dev/null
+++ b/supabase/functions/app_stats/index.ts
@@ -0,0 +1,108 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { sendRes } from '../_utils/utils.ts'
+
+const getApp = (appId: string) => {
+ const supabase = supabaseAdmin
+ const now = new Date()
+ const firstDay = new Date(now.getFullYear(), now.getMonth(), 1)
+ const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0)
+ // console.log('req', req)
+ return {
+ mlu: supabase
+ .from('stats')
+ .select('*', { count: 'exact', head: true })
+ .eq('app_id', appId)
+ .lte('created_at', lastDay.toISOString())
+ .gte('created_at', firstDay.toISOString())
+ .eq('action', 'get'),
+ mlu_real: supabase
+ .from('stats')
+ .select('*', { count: 'exact', head: true })
+ .eq('app_id', appId)
+ .lte('created_at', lastDay.toISOString())
+ .gte('created_at', firstDay.toISOString())
+ .eq('action', 'set'),
+ devices: supabase
+ .from('devices')
+ .select('*', { count: 'exact', head: true })
+ .eq('app_id', appId)
+ .lte('updated_at', lastDay.toISOString())
+ .gte('updated_at', firstDay.toISOString()),
+ versions: supabase
+ .from('app_versions')
+ .select('id', { count: 'exact', head: true })
+ .eq('app_id', appId),
+ shared: supabase
+ .from('channel_users')
+ .select('id', { count: 'exact', head: true })
+ .eq('app_id', appId),
+ channels: supabase
+ .from('channels')
+ .select('id', { count: 'exact', head: true })
+ .eq('app_id', appId),
+ }
+}
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const API_SECRET = Deno.env.get('API_SECRET')
+ const authorizationSecret = event.headers.get('apisecret')
+ if (!authorizationSecret) {
+ console.error('Cannot find authorization secret')
+ return sendRes({ status: 'Cannot find authorization secret' }, 400)
+ }
+ if (!authorizationSecret || !API_SECRET || authorizationSecret !== API_SECRET) {
+ console.error('Fail Authorization', authorizationSecret, API_SECRET)
+ return sendRes({ message: 'Fail Authorization', authorizationSecret, API_SECRET }, 400)
+ }
+ try {
+ const { data: apps } = await supabase
+ .from('apps')
+ .select()
+
+ if (!apps || !apps.length)
+ return sendRes({ status: 'error', message: 'no apps' })
+ // explore all apps
+ const all = []
+ for (const app of apps) {
+ if (!app.id)
+ continue
+ const res = getApp(app.app_id)
+ all.push(Promise.all([app, res.mlu, res.mlu_real, res.versions, res.shared, res.channels, res.devices])
+ .then(([app, mlu, mlu_real, versions, shared, channels, devices]) => {
+ if (!app.app_id)
+ return
+ // console.log('app', app.app_id, downloads, versions, shared, channels)
+ // create var date_id with yearn-month
+ const now = new Date()
+ // get month with leading zero
+ const month = now.getMonth() + 1 < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1})`
+ const newData: definitions['app_stats'] = {
+ app_id: app.app_id,
+ date_id: `${now.getFullYear()}-${month}`,
+ user_id: app.user_id,
+ channels: channels.count || 0,
+ mlu: mlu.count || 0,
+ devices: devices.count || 0,
+ mlu_real: mlu_real.count || 0,
+ versions: versions.count || 0,
+ shared: shared.count || 0,
+ }
+ // console.log('newData', newData)
+ return supabase
+ .from('app_stats')
+ .upsert(newData)
+ }))
+ }
+ await Promise.all(all)
+ return sendRes()
+ }
+ catch (e) {
+ console.error(e)
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/channel/index.ts b/supabase/functions/channel/index.ts
new file mode 100644
index 0000000000..82db6d5597
--- /dev/null
+++ b/supabase/functions/channel/index.ts
@@ -0,0 +1,64 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+// import { isAllowInMyPlan } from '../_utils/plan.ts'
+import { checkAppOwner, supabaseAdmin, updateOrCreateChannel } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { checkKey, sendRes } from '../_utils/utils.ts'
+
+interface ChannelSet {
+ appid: string
+ channel: string
+ version?: string
+ public?: boolean
+}
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('apikey')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ const apikey: definitions['apikeys'] | null = await checkKey(authorization, supabase, ['upload', 'all', 'write'])
+ if (!apikey || !event.body)
+ return sendRes({ status: 'Cannot Verify User' }, 400)
+ try {
+ const body = (await event.json()) as ChannelSet
+ // if (!(await isAllowInMyPlan(apikey.user_id)))
+ // return sendRes({ status: `Your reached the limit of your plan, upgrade to continue ${Deno.env.get('WEBAPP_URL')}/usage` }, 400)
+
+ if (!await checkAppOwner(apikey.user_id, body.appid))
+ return sendRes({ status: 'App missing or your are not the owner' }, 400)
+ const channel: Partial = {
+ created_by: apikey.user_id,
+ app_id: body.appid,
+ name: body.channel,
+ }
+ if (body.version) {
+ const { data, error: vError } = await supabase
+ .from('app_versions')
+ .select()
+ .eq('app_id', body.appid)
+ .eq('name', body.version)
+ .eq('user_id', apikey.user_id)
+ .eq('deleted', false)
+ if (vError || !data || !data.length)
+ return sendRes({ status: `Cannot find version ${body.version}`, error: JSON.stringify(vError) }, 400)
+ channel.version = data[0].id
+ }
+ if (body.public !== undefined)
+ channel.public = body.public
+ try {
+ const { error: dbError } = await updateOrCreateChannel(channel)
+ if (dbError)
+ return sendRes({ status: 'Cannot set channels', error: JSON.stringify(dbError) }, 400)
+ }
+ catch (e) {
+ return sendRes({ status: 'Cannot set channels', error: e }, 500)
+ }
+ return sendRes()
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/delete/index.ts b/supabase/functions/delete/index.ts
new file mode 100644
index 0000000000..605763d3d5
--- /dev/null
+++ b/supabase/functions/delete/index.ts
@@ -0,0 +1,143 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { checkAppOwner, supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { checkKey, sendRes } from '../_utils/utils.ts'
+
+interface AppDelete {
+ appid: string
+ version?: string
+ name: string
+ icon: string
+ iconType: string
+}
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('apikey')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ const apikey: definitions['apikeys'] | null = await checkKey(authorization, supabase, ['upload', 'all', 'write'])
+ if (!apikey || !event.body)
+ return sendRes({ status: 'Cannot Verify User' }, 400)
+ try {
+ const body = (await event.json()) as AppDelete
+ if (!(await checkAppOwner(apikey.user_id, body.appid)))
+ return sendRes({ status: 'You can\'t edit this app' }, 400)
+ if (body.version) {
+ const { data: versions, error: versionIdError } = await supabase
+ .from('app_versions')
+ .select()
+ .eq('app_id', body.appid)
+ .eq('user_id', apikey.user_id)
+ .eq('name', body.version)
+ .eq('deleted', false)
+ if (!versions || !versions.length || versionIdError)
+ return sendRes({ status: `Version ${body.appid}@${body.version} don't exist`, error: versionIdError }, 400)
+ const { data: channelFound, error: errorChannel } = await supabase
+ .from('channels')
+ .select()
+ .eq('app_id', body.appid)
+ .eq('created_by', apikey.user_id)
+ .eq('version', versions[0].id)
+ if ((channelFound && channelFound.length) || errorChannel)
+ return sendRes({ status: `Version ${body.appid}@${body.version} is used in a channel, unlink it first`, error: errorChannel }, 400)
+ const { data: deviceFound, error: errorDevice } = await supabase
+ .from('devices_override')
+ .select()
+ .eq('app_id', body.appid)
+ .eq('version', versions[0].id)
+ if ((deviceFound && deviceFound.length) || errorDevice)
+ return sendRes({ status: `Version ${body.appid}@${body.version} is used in a device override, unlink it first`, error: errorChannel }, 400)
+ // Delete only a specific version in storage
+ const { error: delError } = await supabase
+ .storage
+ .from('apps')
+ .remove([`${apikey.user_id}/${body.appid}/versions/${versions[0].bucket_id}`])
+ if (delError)
+ return sendRes({ status: `Something went wrong when trying to delete ${body.appid}@${body.version}`, error: delError }, 400)
+
+ const { error: delAppSpecVersionError } = await supabase
+ .from('app_versions')
+ .update({
+ deleted: true,
+ })
+ .eq('app_id', body.appid)
+ .eq('name', body.version)
+ .eq('user_id', apikey.user_id)
+ if (delAppSpecVersionError)
+ return sendRes({ status: `App ${body.appid}@${body.version} not found in database`, error: delAppSpecVersionError }, 400)
+ return sendRes()
+ }
+ const { error: delChannelUserError } = await supabase
+ .from('channel_users')
+ .delete()
+ .eq('app_id', body.appid)
+ const { error: delAppStatsVersionError } = await supabase
+ .from('stats')
+ .delete()
+ .eq('app_id', body.appid)
+ const { error: delDevicesVersionError } = await supabase
+ .from('devices')
+ .delete()
+ .eq('app_id', body.appid)
+
+ if (delDevicesVersionError || delAppStatsVersionError || delChannelUserError) {
+ return sendRes({
+ status: `Something went wrong when trying to delete ${body.appid}@${body.version}`,
+ error: delDevicesVersionError || delAppStatsVersionError || delChannelUserError,
+ }, 400)
+ }
+ const { data, error: vError } = await supabase
+ .from('app_versions')
+ .select()
+ .eq('app_id', body.appid)
+ .eq('user_id', apikey.user_id)
+
+ if (vError)
+ return sendRes({ status: `App ${body.appid} not found in database`, error: vError }, 400)
+
+ const { error: delChanError } = await supabase
+ .from('channels')
+ .delete()
+ .eq('app_id', body.appid)
+ .eq('created_by', apikey.user_id)
+
+ if (delChanError)
+ return sendRes({ status: `Cannot delete channel version for app ${body.appid} from database`, error: delChanError }, 400)
+
+ if (data && data.length) {
+ const filesToRemove = data.map(x => `${apikey.user_id}/${body.appid}/versions/${x.bucket_id}`)
+ const { error: delError } = await supabase
+ .storage
+ .from('apps')
+ .remove(filesToRemove)
+ if (delError)
+ return sendRes({ status: `Cannot delete stored version for app ${body.appid} from storage`, error: delError }, 400)
+ }
+
+ const { error: delAppVersionError } = await supabase
+ .from('app_versions')
+ .delete()
+ .eq('app_id', body.appid)
+ .eq('user_id', apikey.user_id)
+
+ if (delAppVersionError)
+ return sendRes({ status: `Cannot delete version for app ${body.appid} from database`, error: delAppVersionError }, 400)
+
+ const { error: dbAppError } = await supabase
+ .from('apps')
+ .delete()
+ .eq('app_id', body.appid)
+ .eq('user_id', apikey.user_id)
+
+ if (dbAppError)
+ return sendRes({ status: 'Cannot delete version from database', error: dbAppError }, 400)
+ return sendRes()
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/demo/index.ts b/supabase/functions/demo/index.ts
new file mode 100644
index 0000000000..6b091ae2e2
--- /dev/null
+++ b/supabase/functions/demo/index.ts
@@ -0,0 +1,32 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { checkKey, sendRes } from '../_utils/utils.ts'
+
+interface dataDemo {
+ appid: string
+ name: string
+ icon: string
+ iconType: string
+}
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('apikey')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ const apikey: definitions['apikeys'] | null = await checkKey(authorization, supabase, ['upload', 'all', 'write'])
+ if (!apikey || !event.body)
+ return sendRes({ status: 'Cannot Verify User' }, 400)
+ try {
+ const body = (await event.json()) as dataDemo
+ console.log('body', body)
+ return sendRes()
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/device/index.ts b/supabase/functions/device/index.ts
new file mode 100644
index 0000000000..6b091ae2e2
--- /dev/null
+++ b/supabase/functions/device/index.ts
@@ -0,0 +1,32 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { checkKey, sendRes } from '../_utils/utils.ts'
+
+interface dataDemo {
+ appid: string
+ name: string
+ icon: string
+ iconType: string
+}
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('apikey')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ const apikey: definitions['apikeys'] | null = await checkKey(authorization, supabase, ['upload', 'all', 'write'])
+ if (!apikey || !event.body)
+ return sendRes({ status: 'Cannot Verify User' }, 400)
+ try {
+ const body = (await event.json()) as dataDemo
+ console.log('body', body)
+ return sendRes()
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/payment_status/index.ts b/supabase/functions/payment_status/index.ts
new file mode 100644
index 0000000000..222fd5bfbc
--- /dev/null
+++ b/supabase/functions/payment_status/index.ts
@@ -0,0 +1,42 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import { currentPaymentstatus } from '../_utils/plans.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { sendOptionsRes, sendRes } from '../_utils/utils.ts'
+
+serve(async(event: Request) => {
+ if (event.method === 'OPTIONS')
+ return sendOptionsRes()
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('authorization')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ try {
+ const { user: auth, error } = await supabase.auth.api.getUser(
+ authorization?.split('Bearer ')[1],
+ )
+
+ if (error || !auth)
+ return sendRes({ status: 'not authorize' }, 400)
+ // get user from users
+ let user: definitions['users']
+
+ const { data: users } = await supabase
+ .from('users')
+ .select()
+ .eq('id', auth.id)
+ if (users && users.length)
+ user = users[0]
+ else
+ return Promise.reject(Error('no user found'))
+ const paymentStatus = await currentPaymentstatus(user)
+
+ return sendRes(paymentStatus)
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknown',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/stripe_checkout/index.ts b/supabase/functions/stripe_checkout/index.ts
new file mode 100644
index 0000000000..0011155d16
--- /dev/null
+++ b/supabase/functions/stripe_checkout/index.ts
@@ -0,0 +1,53 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { sendOptionsRes, sendRes } from '../_utils/utils.ts'
+import { createCheckout } from '../_utils/stripe.ts'
+
+// FIX: https://github.com/stripe-samples/stripe-node-deno-samples/issues/1
+interface PortalData {
+ priceId: string
+ reccurence: 'month' | 'year'
+ successUrl: string
+ cancelUrl: string
+}
+serve(async(event: Request) => {
+ console.log('method', event.method)
+ if (event.method === 'OPTIONS')
+ return sendOptionsRes()
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('authorization')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ try {
+ const body = (await event.json()) as PortalData
+ const { user: auth, error } = await supabase.auth.api.getUser(
+ authorization?.split('Bearer ')[1],
+ )
+ // eslint-disable-next-line no-console
+ // console.log('auth', auth)
+ if (error || !auth)
+ return sendRes({ status: 'not authorize' }, 400)
+ // get user from users
+ const { data: users, error: dbError } = await supabase
+ .from('users')
+ .select()
+ .eq('id', auth.id)
+ if (dbError || !users || !users.length)
+ return sendRes({ status: 'not authorize' }, 400)
+ const user = users[0]
+ if (!user.customer_id)
+ return sendRes({ status: 'no customer' }, 400)
+ // eslint-disable-next-line no-console
+ // console.log('user', user)
+ // key: string, priceId: string, successUrl: string, cancelUrl: string
+ const checkout = await createCheckout(Deno.env.get('STRIPE_SECRET_KEY') || '', user.customer_id, body.reccurence || 'month', body.priceId || 'price_1KkINoGH46eYKnWwwEi97h1B', body.successUrl || 'https://web.capgo.app/app/usage', body.cancelUrl || 'https://web.capgo.app/app/usage')
+ return sendRes({ url: checkout.url })
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/stripe_create_customer/index.ts b/supabase/functions/stripe_create_customer/index.ts
new file mode 100644
index 0000000000..2df3dffc83
--- /dev/null
+++ b/supabase/functions/stripe_create_customer/index.ts
@@ -0,0 +1,46 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { createCustomer } from '../_utils/stripe.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { sendRes } from '../_utils/utils.ts'
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const API_SECRET = Deno.env.get('API_SECRET')
+ const authorizationSecret = event.headers.get('apisecret')
+ if (!authorizationSecret)
+ return sendRes({ status: 'Cannot find authorization secret' }, 400)
+ if (!authorizationSecret || !API_SECRET || authorizationSecret !== API_SECRET) {
+ console.error('Fail Authorization')
+ return sendRes({ message: 'Fail Authorization' }, 400)
+ }
+ try {
+ const body = (await event.json()) as { record: definitions['users'] }
+ const record = body.record
+ if (record.customer_id)
+ return sendRes()
+ const customer = await createCustomer(Deno.env.get('process.env.STRIPE_SECRET_KEY') || '', record.email)
+ const { error: dbStripeError } = await supabase
+ .from('stripe_info')
+ .insert({
+ customer_id: customer.id,
+ })
+ const { error: dbError } = await supabase
+ .from('users')
+ .update({
+ customer_id: customer.id,
+ })
+ .eq('email', record.email)
+ if (dbError || dbStripeError) {
+ console.error(dbError)
+ return sendRes({ message: dbError }, 400)
+ }
+ return sendRes()
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/stripe_event/index.ts b/supabase/functions/stripe_event/index.ts
new file mode 100644
index 0000000000..bac752b285
--- /dev/null
+++ b/supabase/functions/stripe_event/index.ts
@@ -0,0 +1,36 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { extractDataEvent, parseStripeEvent } from '../_utils/stripe.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { sendRes } from '../_utils/utils.ts'
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+
+ if (!event.headers.get('stripe-signature') || !Deno.env.get('STRIPE_WEBHOOK_SECRET') || !Deno.env.get('STRIPE_SECRET_KEY'))
+ return sendRes({ status: 'Webhook Error: no signature or no secret found' }, 400)
+
+ // event.headers
+ try {
+ const stripeEvent = await extractDataEvent(parseStripeEvent(Deno.env.get('STRIPE_SECRET_KEY') || '', await event.text(), event.headers.get('stripe-signature') || '', Deno.env.get('STRIPE_WEBHOOK_SECRET') || ''))
+ if (stripeEvent.customer_id === '')
+ return sendRes('no customer found', 500)
+
+ const { error: dbError } = await supabase
+ .from('stripe_info')
+ .update(stripeEvent)
+ .eq('customer_id', stripeEvent.customer_id)
+ // eslint-disable-next-line no-console
+ console.log('stripeEvent', stripeEvent)
+ if (dbError)
+ return sendRes(dbError, 500)
+
+ return sendRes({ received: true })
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/stripe_portal/index.ts b/supabase/functions/stripe_portal/index.ts
new file mode 100644
index 0000000000..2a7218f79b
--- /dev/null
+++ b/supabase/functions/stripe_portal/index.ts
@@ -0,0 +1,49 @@
+import { serve } from 'https://deno.land/std@0.139.0/http/server.ts'
+import { createPortal } from '../_utils/stripe.ts'
+import { supabaseAdmin } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { sendOptionsRes, sendRes } from '../_utils/utils.ts'
+
+interface PortalData {
+ callbackUrl: string
+}
+
+serve(async(event: Request) => {
+ console.log('method', event.method)
+ if (event.method === 'OPTIONS')
+ return sendOptionsRes()
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('authorization')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ try {
+ const body = (await event.json()) as PortalData
+ const { user: auth, error } = await supabase.auth.api.getUser(
+ authorization?.split('Bearer ')[1],
+ )
+ // eslint-disable-next-line no-console
+ // console.log('auth', auth)
+ if (error || !auth)
+ return sendRes({ status: 'not authorize' }, 400)
+ // get user from users
+ const { data: users, error: dbError } = await supabase
+ .from('users')
+ .select()
+ .eq('id', auth.id)
+ if (dbError || !users || !users.length)
+ return sendRes({ status: 'not authorize' }, 400)
+ const user = users[0]
+ if (!user.customer_id)
+ return sendRes({ status: 'no customer' }, 400)
+ // eslint-disable-next-line no-console
+ // console.log('user', user)
+ const link = await createPortal(Deno.env.get('STRIPE_SECRET_KEY') || '', user.customer_id, body.callbackUrl || 'https://web.capgo.app/app/usage')
+ return sendRes({ url: link.url })
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})
diff --git a/supabase/functions/upload/index.ts b/supabase/functions/upload/index.ts
new file mode 100644
index 0000000000..11b222ef44
--- /dev/null
+++ b/supabase/functions/upload/index.ts
@@ -0,0 +1,138 @@
+import { serve } from 'https://deno.land/std@0.133.0/http/server.ts'
+import { Buffer } from 'https://deno.land/x/node_buffer@1.1.0/index.ts'
+// import { isAllowInMyPlan } from '../_utils/plan.ts'
+import { supabaseAdmin, updateOrCreateChannel, updateOrCreateVersion } from '../_utils/supabase.ts'
+import type { definitions } from '../_utils/types_supabase.ts'
+import { checkKey, sendRes } from '../_utils/utils.ts'
+
+interface AppUpload {
+ appid: string
+ version: string
+ app: string
+ format?: string
+ fileName?: string
+ isMultipart?: boolean
+ external?: string
+ chunk?: number
+ totalChunks?: number
+ channel: string
+}
+
+serve(async(event: Request) => {
+ const supabase = supabaseAdmin
+ const authorization = event.headers.get('apikey')
+ if (!authorization)
+ return sendRes({ status: 'Cannot find authorization' }, 400)
+ const apikey: definitions['apikeys'] | null = await checkKey(authorization, supabase, ['upload', 'all', 'write'])
+ if (!apikey || !event.body)
+ return sendRes({ status: 'Cannot Verify User' }, 400)
+ try {
+ // if (!(await isAllowInMyPlan(apikey.user_id)))
+ // return sendRes({ status: `Your reached the limit of your plan, upgrade to continue ${Deno.env.get('WEBAPP_URL')}/usage` }, 400)
+ const body = (await event.json()) as AppUpload
+ const { data: appData, error: dbError0 } = await supabase
+ .from('apps')
+ .select()
+ .eq('app_id', body.appid)
+ .eq('user_id', apikey.user_id)
+ if (!appData?.length || dbError0)
+ return sendRes({ status: `Cannot find app ${body.appid} in your account` }, 400)
+ if (body.totalChunks && body.totalChunks > 30)
+ return sendRes({ status: 'app too big', error: 'we dont support app above 30 Mb for now, try to optimise your assets.' }, 400)
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { app, ...newObject } = body
+ // eslint-disable-next-line no-console
+ console.log('body', newObject)
+ let fileName = globalThis.crypto.randomUUID()
+ const filePath = `apps/${apikey.user_id}/${body.appid}/versions`
+ const dataFormat = body.format || 'base64'
+ let error
+ if (body.isMultipart && body.fileName && !body.external) {
+ fileName = body.fileName
+ const { data, error: dnError } = await supabase
+ .storage
+ .from(filePath)
+ .download(fileName)
+ if (dnError || !data)
+ return sendRes({ status: 'Cannot download partial File to concat', error: JSON.stringify(dnError || { err: 'unknow error' }) }, 400)
+ const arrayBuffer = await data.arrayBuffer()
+ const buffOld = Buffer.from(arrayBuffer)
+ const buffNew = Buffer.from(app, dataFormat)
+ const bufAll = Buffer.concat([buffOld, buffNew], buffOld.length + buffNew.length)
+ const { error: upError } = await supabase
+ .storage
+ .from(filePath)
+ .update(fileName, bufAll, {
+ contentType: 'application/zip',
+ upsert: true,
+ })
+ error = upError
+ }
+ else if (!body.external) {
+ const { error: upError } = await supabase.storage
+ .from(filePath)
+ .upload(fileName, Buffer.from(app, dataFormat), {
+ contentType: 'application/zip',
+ })
+ error = upError
+ }
+ if (error) {
+ console.error(error, 'unknow error')
+ return sendRes({ status: 'Cannot Upload File', error: JSON.stringify(error) }, 400)
+ }
+ if (body.isMultipart && !((body.chunk || 0) === (body.totalChunks || 0) && body.fileName))
+ return sendRes({ status: 'multipart', fileName })
+
+ if (body.external && !body.external.startsWith('https://'))
+ return sendRes({ status: 'external refused', error: `it should start with "https://" current is "${body.external}"` }, 400)
+ const { data: version, error: dbError } = await updateOrCreateVersion({
+ bucket_id: body.external ? undefined : fileName,
+ user_id: apikey.user_id,
+ name: body.version,
+ app_id: body.appid,
+ external_url: body.external,
+ })
+ const { error: dbError2 } = await supabase
+ .from('apps')
+ .update({
+ last_version: body.version,
+ }).eq('app_id', body.appid)
+ .eq('user_id', apikey.user_id)
+ if (dbError || dbError2 || !version || !version.length) {
+ console.error(dbError, dbError2, 'unknow error')
+ return sendRes({
+ status: 'Cannot add version',
+ err: JSON.stringify(dbError || dbError2 || { err: 'unknow error' }),
+ }, 400)
+ }
+ try {
+ const { error: dbError3 } = await updateOrCreateChannel({
+ name: body.channel,
+ app_id: body.appid,
+ created_by: apikey.user_id,
+ version: version[0].id,
+ })
+ if (dbError3) {
+ console.error(dbError3, 'unknow error')
+ return sendRes({
+ status: 'Cannot update or add channel',
+ error: JSON.stringify(dbError3),
+ }, 400)
+ }
+ }
+ catch (err) {
+ console.error(err, 'unknow error')
+ return sendRes({
+ status: 'Error channel',
+ error: JSON.stringify(err),
+ }, 400)
+ }
+ return sendRes({ status: 'done', fileName })
+ }
+ catch (e) {
+ return sendRes({
+ status: 'Error unknow',
+ error: JSON.stringify(e),
+ }, 500)
+ }
+})