@better-auth/infra 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +22 -27
- package/dist/index.mjs +102 -70
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -723,7 +723,7 @@ interface DashIdRow {
|
|
|
723
723
|
id: string;
|
|
724
724
|
}
|
|
725
725
|
//#endregion
|
|
726
|
-
//#region ../../node_modules/.bun/@better-auth+scim@1.6.1+
|
|
726
|
+
//#region ../../node_modules/.bun/@better-auth+scim@1.6.1+27eabf8bb9704597/node_modules/@better-auth/scim/dist/index.d.mts
|
|
727
727
|
//#region src/types.d.ts
|
|
728
728
|
interface SCIMProvider {
|
|
729
729
|
id: string;
|
|
@@ -4507,34 +4507,29 @@ interface DashUserOrganizationsResponse {
|
|
|
4507
4507
|
}
|
|
4508
4508
|
type DashCreateUserResponse = DashUser;
|
|
4509
4509
|
type DashUpdateUserResponse = DashUser;
|
|
4510
|
+
/** One period of sign-up stats; null when the underlying query failed. */
|
|
4511
|
+
interface DashUserStatsSignUpPeriod {
|
|
4512
|
+
signUps: number | null;
|
|
4513
|
+
/** Omitted when current or previous-period query failed (avoids misleading deltas). */
|
|
4514
|
+
percentage: number | null;
|
|
4515
|
+
}
|
|
4516
|
+
/** One period of active-user stats; null when the underlying query failed. */
|
|
4517
|
+
interface DashUserStatsActivePeriod {
|
|
4518
|
+
active: number | null;
|
|
4519
|
+
percentage: number | null;
|
|
4520
|
+
}
|
|
4510
4521
|
interface DashUserStatsResponse {
|
|
4511
|
-
daily:
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
weekly: {
|
|
4516
|
-
signUps: number;
|
|
4517
|
-
percentage: number;
|
|
4518
|
-
};
|
|
4519
|
-
monthly: {
|
|
4520
|
-
signUps: number;
|
|
4521
|
-
percentage: number;
|
|
4522
|
-
};
|
|
4523
|
-
total: number;
|
|
4522
|
+
daily: DashUserStatsSignUpPeriod;
|
|
4523
|
+
weekly: DashUserStatsSignUpPeriod;
|
|
4524
|
+
monthly: DashUserStatsSignUpPeriod;
|
|
4525
|
+
total: number | null;
|
|
4524
4526
|
activeUsers: {
|
|
4525
|
-
daily:
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
};
|
|
4529
|
-
weekly: {
|
|
4530
|
-
active: number;
|
|
4531
|
-
percentage: number;
|
|
4532
|
-
};
|
|
4533
|
-
monthly: {
|
|
4534
|
-
active: number;
|
|
4535
|
-
percentage: number;
|
|
4536
|
-
};
|
|
4527
|
+
daily: DashUserStatsActivePeriod;
|
|
4528
|
+
weekly: DashUserStatsActivePeriod;
|
|
4529
|
+
monthly: DashUserStatsActivePeriod;
|
|
4537
4530
|
};
|
|
4531
|
+
/** Set when any stat query failed; some fields may be null. */
|
|
4532
|
+
degraded?: boolean;
|
|
4538
4533
|
}
|
|
4539
4534
|
interface DashUserGraphPoint {
|
|
4540
4535
|
date: string | Date;
|
|
@@ -5874,4 +5869,4 @@ declare const dash: <O extends DashOptions>(options?: O) => {
|
|
|
5874
5869
|
} : {};
|
|
5875
5870
|
};
|
|
5876
5871
|
//#endregion
|
|
5877
|
-
export { type APIError, CHALLENGE_TTL, type CompromisedPasswordResult, type CredentialStuffingResult, DBField, DEFAULT_DIFFICULTY, DashAddTeamMemberResponse, DashBanManyResponse, DashCheckUserByEmailResponse, DashCheckUserExistsResponse, DashCompleteInvitationResponse, DashConfigResponse, DashCreateOrganizationBody, DashCreateOrganizationResponse, DashCreateTeamResponse, DashCreateUserResponse, DashDeleteManyUsersResponse, DashDirectoryCreateResponse, DashDirectoryDeleteResponse, DashDirectoryItem, DashDirectoryRegenerateTokenResponse, DashExecuteAdapterCountResponse, DashExecuteAdapterFindManyResponse, DashExecuteAdapterFindOneResponse, DashExecuteAdapterMutationResponse, DashExecuteAdapterResponse, DashExportOrganizationsResponse, DashIdRow, DashInviteMemberResponse, DashMaybeSuccessResponse, type DashOptions, DashOptionsInternal, DashOrganizationAddMemberResponse, DashOrganizationDeleteManyResponse, DashOrganizationDetailResponse, DashOrganizationInvitationItem, DashOrganizationInvitationListResponse, DashOrganizationInvitationStatusItem, DashOrganizationListResponse, DashOrganizationMember, DashOrganizationMemberListItem, DashOrganizationMemberListResponse, DashOrganizationMemberUser, DashOrganizationOptionsResponse, DashOrganizationTeamItem, DashOrganizationTeamListResponse, DashOrganizationUpdateMemberRoleResponse, DashOrganizationUpdateResponse, DashSendManyVerificationEmailsResponse, DashSessionRevokeManyResponse, DashSsoCreateProviderResponse, DashSsoDeleteResponse, DashSsoMarkDomainVerifiedResponse, DashSsoProviderItem, DashSsoProviderSummary, DashSsoUpdateProviderResponse, DashSsoVerificationTokenResponse, DashSsoVerifyDomainResponse, DashSuccessResponse, DashTeam, DashTeamMember, DashTeamMemberListResponse, DashTwoFactorBackupCodesResponse, DashTwoFactorEnableResponse, DashTwoFactorTotpViewResponse, DashUpdateTeamResponse, DashUpdateUserResponse, DashUserDetailsResponse, DashUserGraphDataResponse, DashUserListResponse, DashUserOrganizationsResponse, DashUserRetentionDataResponse, DashUserStatsResponse, DashValidateResponse, DirectorySyncConnection, EMAIL_TEMPLATES, type EmailConfig, type EmailTemplateId, type EmailTemplateVariables, type Endpoint, type EndpointOptions, type EventLocation, type EventTypesResponse, type ImpossibleTravelResult, InfraEndpointContext, InfraPluginConnectionOptions, InfraPluginConnectionOptionsInternal, LocationData, LocationDataContext, type PoWChallenge, type PoWSolution, SCIMPlugin, type SMSConfig, type SMSTemplateId, type SMSTemplateVariables, SMS_TEMPLATES, type SecurityEvent, type SecurityEventType, type SecurityOptions, type SecurityVerdict, type SendBulkEmailsOptions, type SendBulkEmailsResult, type SendEmailOptions, type SendEmailResult, type SendSMSOptions, type SendSMSResult, type SentinelOptions, SentinelOptionsInternal, type StaleUserResult, type ThresholdConfig, USER_EVENT_TYPES, type UserEvent, type UserEventType, type UserEventsResponse, createEmailSender, createSMSSender, dash, decodePoWChallenge, encodePoWSolution, normalizeEmail, sendBulkEmails, sendEmail, sendSMS, sentinel, solvePoWChallenge, verifyPoWSolution };
|
|
5872
|
+
export { type APIError, CHALLENGE_TTL, type CompromisedPasswordResult, type CredentialStuffingResult, DBField, DEFAULT_DIFFICULTY, DashAddTeamMemberResponse, DashBanManyResponse, DashCheckUserByEmailResponse, DashCheckUserExistsResponse, DashCompleteInvitationResponse, DashConfigResponse, DashCreateOrganizationBody, DashCreateOrganizationResponse, DashCreateTeamResponse, DashCreateUserResponse, DashDeleteManyUsersResponse, DashDirectoryCreateResponse, DashDirectoryDeleteResponse, DashDirectoryItem, DashDirectoryRegenerateTokenResponse, DashExecuteAdapterCountResponse, DashExecuteAdapterFindManyResponse, DashExecuteAdapterFindOneResponse, DashExecuteAdapterMutationResponse, DashExecuteAdapterResponse, DashExportOrganizationsResponse, DashIdRow, DashInviteMemberResponse, DashMaybeSuccessResponse, type DashOptions, DashOptionsInternal, DashOrganizationAddMemberResponse, DashOrganizationDeleteManyResponse, DashOrganizationDetailResponse, DashOrganizationInvitationItem, DashOrganizationInvitationListResponse, DashOrganizationInvitationStatusItem, DashOrganizationListResponse, DashOrganizationMember, DashOrganizationMemberListItem, DashOrganizationMemberListResponse, DashOrganizationMemberUser, DashOrganizationOptionsResponse, DashOrganizationTeamItem, DashOrganizationTeamListResponse, DashOrganizationUpdateMemberRoleResponse, DashOrganizationUpdateResponse, DashSendManyVerificationEmailsResponse, DashSessionRevokeManyResponse, DashSsoCreateProviderResponse, DashSsoDeleteResponse, DashSsoMarkDomainVerifiedResponse, DashSsoProviderItem, DashSsoProviderSummary, DashSsoUpdateProviderResponse, DashSsoVerificationTokenResponse, DashSsoVerifyDomainResponse, DashSuccessResponse, DashTeam, DashTeamMember, DashTeamMemberListResponse, DashTwoFactorBackupCodesResponse, DashTwoFactorEnableResponse, DashTwoFactorTotpViewResponse, DashUpdateTeamResponse, DashUpdateUserResponse, DashUserDetailsResponse, DashUserGraphDataResponse, DashUserListResponse, DashUserOrganizationsResponse, DashUserRetentionDataResponse, DashUserStatsActivePeriod, DashUserStatsResponse, DashUserStatsSignUpPeriod, DashValidateResponse, DirectorySyncConnection, EMAIL_TEMPLATES, type EmailConfig, type EmailTemplateId, type EmailTemplateVariables, type Endpoint, type EndpointOptions, type EventLocation, type EventTypesResponse, type ImpossibleTravelResult, InfraEndpointContext, InfraPluginConnectionOptions, InfraPluginConnectionOptionsInternal, LocationData, LocationDataContext, type PoWChallenge, type PoWSolution, SCIMPlugin, type SMSConfig, type SMSTemplateId, type SMSTemplateVariables, SMS_TEMPLATES, type SecurityEvent, type SecurityEventType, type SecurityOptions, type SecurityVerdict, type SendBulkEmailsOptions, type SendBulkEmailsResult, type SendEmailOptions, type SendEmailResult, type SendSMSOptions, type SendSMSResult, type SentinelOptions, SentinelOptionsInternal, type StaleUserResult, type ThresholdConfig, USER_EVENT_TYPES, type UserEvent, type UserEventType, type UserEventsResponse, createEmailSender, createSMSSender, dash, decodePoWChallenge, encodePoWSolution, normalizeEmail, sendBulkEmails, sendEmail, sendSMS, sentinel, solvePoWChallenge, verifyPoWSolution };
|
package/dist/index.mjs
CHANGED
|
@@ -958,8 +958,8 @@ function createIdentificationMiddleware(options) {
|
|
|
958
958
|
return;
|
|
959
959
|
}
|
|
960
960
|
const ipAddress = getClientIpFromRequest(ctx.request, ipConfig?.ipAddressHeaders || null);
|
|
961
|
-
|
|
962
|
-
|
|
961
|
+
if (ipAddress) {
|
|
962
|
+
const countryCode = getCountryCodeFromRequest(ctx.request);
|
|
963
963
|
ctx.context.location = {
|
|
964
964
|
ipAddress,
|
|
965
965
|
countryCode
|
|
@@ -2746,7 +2746,7 @@ const jwtValidateMiddleware = (options) => createAuthMiddleware(async (ctx) => {
|
|
|
2746
2746
|
});
|
|
2747
2747
|
//#endregion
|
|
2748
2748
|
//#region src/version.ts
|
|
2749
|
-
const PLUGIN_VERSION = "0.2.
|
|
2749
|
+
const PLUGIN_VERSION = "0.2.2";
|
|
2750
2750
|
//#endregion
|
|
2751
2751
|
//#region src/routes/auth/config.ts
|
|
2752
2752
|
const PLUGIN_OPTIONS_EXCLUDE_KEYS = { stripe: new Set(["stripeClient"]) };
|
|
@@ -2758,23 +2758,28 @@ function isPlainSerializable(value) {
|
|
|
2758
2758
|
if (constructor && constructor.name !== "Object" && constructor.name !== "Array") return false;
|
|
2759
2759
|
return true;
|
|
2760
2760
|
}
|
|
2761
|
-
function sanitizePluginOptions(pluginId, options,
|
|
2761
|
+
function sanitizePluginOptions(pluginId, options, visiting = /* @__PURE__ */ new WeakSet()) {
|
|
2762
2762
|
if (options === null || options === void 0) return options;
|
|
2763
2763
|
if (typeof options === "function") return void 0;
|
|
2764
2764
|
if (typeof options !== "object") return options;
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2765
|
+
const obj = options;
|
|
2766
|
+
if (visiting.has(obj)) return void 0;
|
|
2767
|
+
visiting.add(obj);
|
|
2768
|
+
try {
|
|
2769
|
+
const excludeKeys = PLUGIN_OPTIONS_EXCLUDE_KEYS[pluginId];
|
|
2770
|
+
if (Array.isArray(options)) return options.map((item) => sanitizePluginOptions(pluginId, item, visiting)).filter((item) => item !== void 0);
|
|
2771
|
+
const result = {};
|
|
2772
|
+
for (const [key, value] of Object.entries(options)) {
|
|
2773
|
+
if (excludeKeys?.has(key)) continue;
|
|
2774
|
+
if (typeof value === "function") continue;
|
|
2775
|
+
if (value !== null && typeof value === "object" && !isPlainSerializable(value)) continue;
|
|
2776
|
+
const sanitized = sanitizePluginOptions(pluginId, value, visiting);
|
|
2777
|
+
if (sanitized !== void 0) result[key] = sanitized;
|
|
2778
|
+
}
|
|
2779
|
+
return result;
|
|
2780
|
+
} finally {
|
|
2781
|
+
visiting.delete(obj);
|
|
2776
2782
|
}
|
|
2777
|
-
return result;
|
|
2778
2783
|
}
|
|
2779
2784
|
function estimateEntropy(str) {
|
|
2780
2785
|
const unique = new Set(str).size;
|
|
@@ -6625,7 +6630,7 @@ async function countUniqueActiveUsers(ctx, range, options) {
|
|
|
6625
6630
|
break;
|
|
6626
6631
|
}
|
|
6627
6632
|
}
|
|
6628
|
-
}, { concurrency:
|
|
6633
|
+
}, { concurrency: 10 });
|
|
6629
6634
|
return activeUserIds.size;
|
|
6630
6635
|
}
|
|
6631
6636
|
const sessions = await ctx.context.adapter.findMany({
|
|
@@ -6635,6 +6640,34 @@ async function countUniqueActiveUsers(ctx, range, options) {
|
|
|
6635
6640
|
});
|
|
6636
6641
|
return new Set(sessions.map((s) => s.userId)).size;
|
|
6637
6642
|
}
|
|
6643
|
+
function optionalQuery(ctx, label, getCount) {
|
|
6644
|
+
return async function runQuery() {
|
|
6645
|
+
try {
|
|
6646
|
+
return {
|
|
6647
|
+
ok: true,
|
|
6648
|
+
value: await getCount()
|
|
6649
|
+
};
|
|
6650
|
+
} catch (error) {
|
|
6651
|
+
ctx.context.logger.warn(`[Dash] User stats query "${label}" failed`, error);
|
|
6652
|
+
return {
|
|
6653
|
+
ok: false,
|
|
6654
|
+
value: null
|
|
6655
|
+
};
|
|
6656
|
+
}
|
|
6657
|
+
};
|
|
6658
|
+
}
|
|
6659
|
+
function signUpPeriod(current, previous, calculatePercentage) {
|
|
6660
|
+
return {
|
|
6661
|
+
signUps: current.ok ? current.value : null,
|
|
6662
|
+
percentage: current.ok && previous.ok ? calculatePercentage(current.value, previous.value) : null
|
|
6663
|
+
};
|
|
6664
|
+
}
|
|
6665
|
+
function activePeriod(current, previous, calculatePercentage) {
|
|
6666
|
+
return {
|
|
6667
|
+
active: current.ok ? current.value : null,
|
|
6668
|
+
percentage: current.ok && previous.ok ? calculatePercentage(current.value, previous.value) : null
|
|
6669
|
+
};
|
|
6670
|
+
}
|
|
6638
6671
|
const getUserStats = (options) => createAuthEndpoint("/dash/user-stats", {
|
|
6639
6672
|
method: "GET",
|
|
6640
6673
|
use: [jwtMiddleware(options)]
|
|
@@ -6648,16 +6681,16 @@ const getUserStats = (options) => createAuthEndpoint("/dash/user-stats", {
|
|
|
6648
6681
|
const twoMonthsAgo = /* @__PURE__ */ new Date(now.getTime() - 1440 * 60 * 60 * 1e3);
|
|
6649
6682
|
const activityTrackingEnabled = !!options.activityTracking?.enabled;
|
|
6650
6683
|
const storeInSecondaryStorageOnly = isSessionInSecondaryStorageOnly(ctx.context);
|
|
6651
|
-
const [
|
|
6652
|
-
ctx.context.adapter.count({
|
|
6684
|
+
const [rDailySignups, rPrevDaySignups, rWeeklySignups, rPrevWeekSignups, rMonthlySignups, rPrevMonthSignups, rTotalUsers, rActiveDaily, rActivePrevDay, rActiveWeekly, rActivePrevWeek, rActiveMonthly, rActivePrevMonth] = await withConcurrency([
|
|
6685
|
+
optionalQuery(ctx, "daily signups", () => ctx.context.adapter.count({
|
|
6653
6686
|
model: "user",
|
|
6654
6687
|
where: [{
|
|
6655
6688
|
field: "createdAt",
|
|
6656
6689
|
operator: "gte",
|
|
6657
6690
|
value: oneDayAgo
|
|
6658
6691
|
}]
|
|
6659
|
-
}),
|
|
6660
|
-
ctx.context.adapter.count({
|
|
6692
|
+
})),
|
|
6693
|
+
optionalQuery(ctx, "previous day signups", () => ctx.context.adapter.count({
|
|
6661
6694
|
model: "user",
|
|
6662
6695
|
where: [{
|
|
6663
6696
|
field: "createdAt",
|
|
@@ -6668,16 +6701,16 @@ const getUserStats = (options) => createAuthEndpoint("/dash/user-stats", {
|
|
|
6668
6701
|
operator: "lt",
|
|
6669
6702
|
value: oneDayAgo
|
|
6670
6703
|
}]
|
|
6671
|
-
}),
|
|
6672
|
-
ctx.context.adapter.count({
|
|
6704
|
+
})),
|
|
6705
|
+
optionalQuery(ctx, "weekly signups", () => ctx.context.adapter.count({
|
|
6673
6706
|
model: "user",
|
|
6674
6707
|
where: [{
|
|
6675
6708
|
field: "createdAt",
|
|
6676
6709
|
operator: "gte",
|
|
6677
6710
|
value: oneWeekAgo
|
|
6678
6711
|
}]
|
|
6679
|
-
}),
|
|
6680
|
-
ctx.context.adapter.count({
|
|
6712
|
+
})),
|
|
6713
|
+
optionalQuery(ctx, "previous week signups", () => ctx.context.adapter.count({
|
|
6681
6714
|
model: "user",
|
|
6682
6715
|
where: [{
|
|
6683
6716
|
field: "createdAt",
|
|
@@ -6688,16 +6721,16 @@ const getUserStats = (options) => createAuthEndpoint("/dash/user-stats", {
|
|
|
6688
6721
|
operator: "lt",
|
|
6689
6722
|
value: oneWeekAgo
|
|
6690
6723
|
}]
|
|
6691
|
-
}),
|
|
6692
|
-
ctx.context.adapter.count({
|
|
6724
|
+
})),
|
|
6725
|
+
optionalQuery(ctx, "monthly signups", () => ctx.context.adapter.count({
|
|
6693
6726
|
model: "user",
|
|
6694
6727
|
where: [{
|
|
6695
6728
|
field: "createdAt",
|
|
6696
6729
|
operator: "gte",
|
|
6697
6730
|
value: oneMonthAgo
|
|
6698
6731
|
}]
|
|
6699
|
-
}),
|
|
6700
|
-
ctx.context.adapter.count({
|
|
6732
|
+
})),
|
|
6733
|
+
optionalQuery(ctx, "previous month signups", () => ctx.context.adapter.count({
|
|
6701
6734
|
model: "user",
|
|
6702
6735
|
where: [{
|
|
6703
6736
|
field: "createdAt",
|
|
@@ -6708,75 +6741,74 @@ const getUserStats = (options) => createAuthEndpoint("/dash/user-stats", {
|
|
|
6708
6741
|
operator: "lt",
|
|
6709
6742
|
value: oneMonthAgo
|
|
6710
6743
|
}]
|
|
6711
|
-
}),
|
|
6712
|
-
ctx.context.adapter.count({ model: "user" }),
|
|
6713
|
-
countUniqueActiveUsers(ctx, { from: oneDayAgo }, {
|
|
6744
|
+
})),
|
|
6745
|
+
optionalQuery(ctx, "total users", () => ctx.context.adapter.count({ model: "user" })),
|
|
6746
|
+
optionalQuery(ctx, "active users (daily window)", () => countUniqueActiveUsers(ctx, { from: oneDayAgo }, {
|
|
6714
6747
|
storeInSecondaryStorageOnly,
|
|
6715
6748
|
activityTrackingEnabled
|
|
6716
|
-
}),
|
|
6717
|
-
countUniqueActiveUsers(ctx, {
|
|
6749
|
+
})),
|
|
6750
|
+
optionalQuery(ctx, "active users (previous day window)", () => countUniqueActiveUsers(ctx, {
|
|
6718
6751
|
from: twoDaysAgo,
|
|
6719
6752
|
to: oneDayAgo
|
|
6720
6753
|
}, {
|
|
6721
6754
|
storeInSecondaryStorageOnly,
|
|
6722
6755
|
activityTrackingEnabled
|
|
6723
|
-
}),
|
|
6724
|
-
countUniqueActiveUsers(ctx, { from: oneWeekAgo }, {
|
|
6756
|
+
})),
|
|
6757
|
+
optionalQuery(ctx, "active users (weekly window)", () => countUniqueActiveUsers(ctx, { from: oneWeekAgo }, {
|
|
6725
6758
|
storeInSecondaryStorageOnly,
|
|
6726
6759
|
activityTrackingEnabled
|
|
6727
|
-
}),
|
|
6728
|
-
countUniqueActiveUsers(ctx, {
|
|
6760
|
+
})),
|
|
6761
|
+
optionalQuery(ctx, "active users (previous week window)", () => countUniqueActiveUsers(ctx, {
|
|
6729
6762
|
from: twoWeeksAgo,
|
|
6730
6763
|
to: oneWeekAgo
|
|
6731
6764
|
}, {
|
|
6732
6765
|
storeInSecondaryStorageOnly,
|
|
6733
6766
|
activityTrackingEnabled
|
|
6734
|
-
}),
|
|
6735
|
-
countUniqueActiveUsers(ctx, { from: oneMonthAgo }, {
|
|
6767
|
+
})),
|
|
6768
|
+
optionalQuery(ctx, "active users (monthly window)", () => countUniqueActiveUsers(ctx, { from: oneMonthAgo }, {
|
|
6736
6769
|
storeInSecondaryStorageOnly,
|
|
6737
6770
|
activityTrackingEnabled
|
|
6738
|
-
}),
|
|
6739
|
-
countUniqueActiveUsers(ctx, {
|
|
6771
|
+
})),
|
|
6772
|
+
optionalQuery(ctx, "active users (previous month window)", () => countUniqueActiveUsers(ctx, {
|
|
6740
6773
|
from: twoMonthsAgo,
|
|
6741
6774
|
to: oneMonthAgo
|
|
6742
6775
|
}, {
|
|
6743
6776
|
storeInSecondaryStorageOnly,
|
|
6744
6777
|
activityTrackingEnabled
|
|
6745
|
-
})
|
|
6746
|
-
]);
|
|
6778
|
+
}))
|
|
6779
|
+
], (fn) => fn(), { concurrency: 5 });
|
|
6747
6780
|
const calculatePercentage = (current, previous) => {
|
|
6748
6781
|
if (previous === 0) return current > 0 ? 100 : 0;
|
|
6749
6782
|
return (current - previous) / previous * 100;
|
|
6750
6783
|
};
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6784
|
+
const degraded = [
|
|
6785
|
+
rDailySignups,
|
|
6786
|
+
rPrevDaySignups,
|
|
6787
|
+
rWeeklySignups,
|
|
6788
|
+
rPrevWeekSignups,
|
|
6789
|
+
rMonthlySignups,
|
|
6790
|
+
rPrevMonthSignups,
|
|
6791
|
+
rTotalUsers,
|
|
6792
|
+
rActiveDaily,
|
|
6793
|
+
rActivePrevDay,
|
|
6794
|
+
rActiveWeekly,
|
|
6795
|
+
rActivePrevWeek,
|
|
6796
|
+
rActiveMonthly,
|
|
6797
|
+
rActivePrevMonth
|
|
6798
|
+
].some((r) => !r.ok);
|
|
6799
|
+
const body = {
|
|
6800
|
+
daily: signUpPeriod(rDailySignups, rPrevDaySignups, calculatePercentage),
|
|
6801
|
+
weekly: signUpPeriod(rWeeklySignups, rPrevWeekSignups, calculatePercentage),
|
|
6802
|
+
monthly: signUpPeriod(rMonthlySignups, rPrevMonthSignups, calculatePercentage),
|
|
6803
|
+
total: rTotalUsers.ok ? rTotalUsers.value : null,
|
|
6765
6804
|
activeUsers: {
|
|
6766
|
-
daily:
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
},
|
|
6770
|
-
weekly: {
|
|
6771
|
-
active: weeklyActiveCount,
|
|
6772
|
-
percentage: calculatePercentage(weeklyActiveCount, previousWeeklyActiveCount)
|
|
6773
|
-
},
|
|
6774
|
-
monthly: {
|
|
6775
|
-
active: monthlyActiveCount,
|
|
6776
|
-
percentage: calculatePercentage(monthlyActiveCount, previousMonthlyActiveCount)
|
|
6777
|
-
}
|
|
6805
|
+
daily: activePeriod(rActiveDaily, rActivePrevDay, calculatePercentage),
|
|
6806
|
+
weekly: activePeriod(rActiveWeekly, rActivePrevWeek, calculatePercentage),
|
|
6807
|
+
monthly: activePeriod(rActiveMonthly, rActivePrevMonth, calculatePercentage)
|
|
6778
6808
|
}
|
|
6779
6809
|
};
|
|
6810
|
+
if (degraded) body.degraded = true;
|
|
6811
|
+
return body;
|
|
6780
6812
|
});
|
|
6781
6813
|
const getUserGraphData = (options) => createAuthEndpoint("/dash/user-graph-data", {
|
|
6782
6814
|
method: "GET",
|