Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/newjitsu' into newjitsu
Browse files Browse the repository at this point in the history
  • Loading branch information
absorbb committed Nov 23, 2023
2 parents fe89700 + f1a4551 commit 77b0efa
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 53 deletions.
41 changes: 33 additions & 8 deletions libs/jitsu-js/src/analytics-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* global analytics */

import { JitsuOptions, PersistentStorage, RuntimeFacade } from "./jitsu";
import { AnalyticsClientEvent, Callback, ID, JSONObject, Options } from "@jitsu/protocols/analytics";
import { AnalyticsClientEvent, Callback, DispatchedEvent, ID, JSONObject, Options } from "@jitsu/protocols/analytics";
import parse from "./index";

import { AnalyticsInstance, AnalyticsPlugin } from "analytics";
Expand Down Expand Up @@ -63,11 +63,18 @@ function safeCall<T>(f: () => T, defaultVal?: T): T | undefined {
}

function restoreTraits(storage: PersistentStorage) {
const val = storage.getItem("__user_traits");
let val = storage.getItem("__user_traits");
if (typeof val === "string") {
return safeCall(() => JSON.parse(val), {});
val = safeCall(() => JSON.parse(val), {});
}
return val;
let groupVal = storage.getItem("__group_traits");
if (typeof groupVal === "string") {
groupVal = safeCall(() => JSON.parse(groupVal), {});
}
return {
...(groupVal || {}),
...(val || {}), //user traits override group traits
};
}

export type StorageFactory = (cookieDomain: string, cookie2key: Record<string, string>) => PersistentStorage;
Expand Down Expand Up @@ -326,6 +333,7 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
sentAt: new Date().toISOString(),
messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)),
writeKey: maskWriteKey(config.writeKey),
groupId: storage.getItem("__group_id"),
context: deepMerge(context, customContext),
};
delete withContext.meta;
Expand Down Expand Up @@ -478,7 +486,7 @@ async function send(
jitsuConfig: Required<JitsuOptions>,
instance: AnalyticsInstance,
store: PersistentStorage
): Promise<void> {
): Promise<any> {
if (jitsuConfig.echoEvents) {
console.log(`[JITSU DEBUG] sending '${method}' event:`, payload);
return;
Expand Down Expand Up @@ -544,11 +552,19 @@ async function send(
}

if (responseJson.destinations) {
if (jitsuConfig.debug) {
console.log(`[JITSU] Processing device destinations: `, JSON.stringify(responseJson.destinations, null, 2));
if (jitsuConfig.s2s) {
console.warn(
`[JITSU] ${payload.type} responded with list of ${responseJson.destinations.length} destinations. However, this code is running in server-to-server mode, so destinations will be ignored`,
jitsuConfig.debug ? JSON.stringify(responseJson.destinations, null, 2) : undefined
);
} else {
if (jitsuConfig.debug) {
console.log(`[JITSU] Processing device destinations: `, JSON.stringify(responseJson.destinations, null, 2));
}
return processDestinations(responseJson.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
}
return processDestinations(responseJson.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
}
return adjustedPayload;
}

export type JitsuPluginConfig = JitsuOptions & {
Expand Down Expand Up @@ -610,13 +626,22 @@ const jitsuAnalyticsPlugin = (pluginConfig: JitsuPluginConfig = {}): AnalyticsPl
methods: {
//analytics doesn't support group as a base method, so we need to add it manually
group(groupId?: ID, traits?: JSONObject | null, options?: Options, callback?: Callback) {
if (typeof groupId === "number") {
//fix potential issues with group id being used incorrectly
groupId = groupId + "";
}

const analyticsInstance = this.instance;
const cacheWrap = pluginConfig.storageWrapper
? pluginConfig.storageWrapper(analyticsInstance.storage)
: analyticsInstance.storage;
const user = analyticsInstance.user();
const userId = options?.userId || user?.userId;
const anonymousId = options?.anonymousId || user?.anonymousId || cacheWrap.getItem("__anon_id");
cacheWrap.setItem("__group_id", groupId);
if (traits && typeof traits === "object") {
cacheWrap.setItem("__group_traits", traits);
}
return send(
"group",
{ type: "group", groupId, traits, ...(anonymousId ? { anonymousId } : {}), ...(userId ? { userId } : {}) },
Expand Down
14 changes: 11 additions & 3 deletions libs/jitsu-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,21 @@ function createUnderlyingAnalyticsInstance(
(analytics as any).setAnonymousId(id);
}
},
group(groupId?: ID, traits?: JSONObject | null, options?: Options, callback?: Callback): Promise<DispatchedEvent> {
async group(
groupId?: ID,
traits?: JSONObject | null,
options?: Options,
callback?: Callback
): Promise<DispatchedEvent> {
const results: any[] = [];
for (const plugin of Object.values(analytics.plugins)) {
if (plugin["group"]) {
plugin["group"](groupId, traits, options, callback);
results.push(await plugin["group"](groupId, traits, options, callback));
}
}
return Promise.resolve({});
//It's incorrect at many levels. First, it's not a dispatched event. Second, we take a first result
//However, since returned values are used for debugging purposes only, it's ok
return results[0];
},
} as AnalyticsInterface;
}
Expand Down
2 changes: 1 addition & 1 deletion types/protocols/analytics.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ interface ProcessingContext {

export type AnalyticsServerEvent = AnalyticsClientEvent & ServerContext & ProcessingContext;

export type JSONPrimitive = string | number | boolean | null;
export type JSONPrimitive = string | number | boolean | null | undefined;
export type JSONValue = JSONPrimitive | JSONObject | JSONArray;
export type JSONObject = { [member: string]: JSONValue };
export type JSONArray = Array<JSONValue>;
Expand Down
2 changes: 2 additions & 0 deletions types/protocols/async-request.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export type IngestMessage = {
messageId: string;
//currently this not being filled
connectionId: string;
//id of a stream where this message should eventually go. For debugging purposes so far
streamId?: string;
type: string;
origin: {
baseUrl: string;
Expand Down
12 changes: 10 additions & 2 deletions webapps/console/components/PageLayout/WorkspacePageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,14 @@ function PageHeader() {
);
}

const WorkspaceSettingsModal: React.FC<{ onSuccess: () => void }> = ({ onSuccess }) => {
/**
* @param onboarding if the dialog is shown on onboarding page. For onboarding,
* we should issue an event that onboarding is completed
*/
const WorkspaceSettingsModal: React.FC<{ onSuccess: () => void; onboarding: boolean }> = ({
onSuccess,
onboarding,
}) => {
const appConfig = useAppConfig();
const domains = getDomains(appConfig);
const { analytics } = useJitsu();
Expand Down Expand Up @@ -610,7 +617,7 @@ const WorkspaceSettingsModal: React.FC<{ onSuccess: () => void }> = ({ onSuccess
{domains.appBase}/<span className="text-textDark">your-slug</span>
</code>{" "}
</div>
<WorkspaceNameAndSlugEditor onSuccess={onSuccess} offerClassic={true} />
<WorkspaceNameAndSlugEditor onSuccess={onSuccess} offerClassic={false} onboarding={onboarding} />
<div className="text-center my-4">
Got here by mistake?{" "}
<a
Expand Down Expand Up @@ -685,6 +692,7 @@ export const WorkspacePageLayout: React.FC<PropsWithChildren<PageLayoutProps>> =
<div className={`flex-auto ${fullscreen ? "overflow-hidden" : ""} flex flex-col`}>
{!workspace.slug && (
<WorkspaceSettingsModal
onboarding={true}
onSuccess={() => {
router.reload();
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@ function pickSlug(email, name): string {
return ensureLength(username.replace(/[^a-z0-9]/g, ""));
}

/**
* @param onboarding if the dialog is shown on onboarding page. For onboarding,
* we should issue an event that onboarding is completed
*/
export function WorkspaceNameAndSlugEditor({
onSuccess,
displayId,
offerClassic,
onboarding,
}: {
onSuccess?: (newVals: { name: string; slug: string }) => void;
displayId?: boolean;
offerClassic?: boolean;
onboarding?: boolean;
}) {
const workspace = useWorkspace();
const appConfig = useAppConfig();
Expand Down Expand Up @@ -144,7 +150,10 @@ export function WorkspaceNameAndSlugEditor({
return;
}
}
await get(`/api/workspace/${workspace.id}`, { method: "PUT", body: { name, slug } });
await get(`/api/workspace/${workspace.id}?onboarding=${!!onboarding}`, {
method: "PUT",
body: { name, slug },
});
feedbackSuccess("Workspace name has been saved");
if (onSuccess) {
onSuccess({ name, slug });
Expand Down
8 changes: 8 additions & 0 deletions webapps/console/lib/nextauth.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { db } from "./server/db";
import { checkHash, requireDefined } from "juava";
import { ApiError } from "./shared/errors";
import { getServerLog } from "./server/log";
import { withProductAnalytics } from "./server/telemetry";
import { NextApiRequest } from "next";

const crypto = require("crypto");

Expand Down Expand Up @@ -69,6 +71,8 @@ export async function getOrCreateUser(opts: {
loginProvider: string;
name?: string;
email: string;
// we only need this for product analytics, so it's optional
req?: NextApiRequest;
}): Promise<User> {
const { externalId, loginProvider, email, name = email } = opts;
log.atDebug().log(`Signing in user ${JSON.stringify(opts)}`);
Expand All @@ -88,6 +92,10 @@ export async function getOrCreateUser(opts: {
admin,
},
});
await withProductAnalytics(p => p.track("user_created"), {
user: { email, name, internalId: user.id, externalId, loginProvider },
req: opts.req,
});
} else if (user.name !== name || user.email !== email) {
await db.prisma().userProfile.update({ where: { id: user.id }, data: { name, email } });
}
Expand Down
1 change: 0 additions & 1 deletion webapps/console/lib/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export const AppConfig = z.object({
frontendTelemetry: z.object({
enabled: z.boolean(),
host: z.string().optional(),
writeKey: z.string().optional(),
}),
logLevel: z.enum(["debug", "info", "warn", "error"]),
syncs: z.object({
Expand Down
Loading

0 comments on commit 77b0efa

Please sign in to comment.