diff --git a/apps/dashboard/src/app/(app)/[organizationId]/page.tsx b/apps/dashboard/src/app/(app)/[organizationId]/page.tsx index 1b1b08ba..ea705c60 100644 --- a/apps/dashboard/src/app/(app)/[organizationId]/page.tsx +++ b/apps/dashboard/src/app/(app)/[organizationId]/page.tsx @@ -1,10 +1,12 @@ import { LogoSquare } from '@/components/Logo'; import { ProjectCard } from '@/components/projects/project-card'; +import { notFound, redirect } from 'next/navigation'; + import { getOrganizationBySlug, getProjectsByOrganizationSlug, + isWaitlistUserAccepted, } from '@openpanel/db'; -import { notFound, redirect } from 'next/navigation'; import { CreateProject } from './create-project'; @@ -25,18 +27,21 @@ export default async function Page({ params: { organizationId } }: PageProps) { } if (process.env.BLOCK) { - return ( -
-
- -

Not quite there yet

-
- We're still working on Openpanel, but we're not quite there yet. - We'll let you know when we're ready to go! + const isAccepted = await isWaitlistUserAccepted(); + if (!isAccepted) { + return ( +
+
+ +

Not quite there yet

+
+ We're still working on Openpanel, but we're not quite there yet. + We'll let you know when we're ready to go! +
-
- ); + ); + } } if (projects.length === 0) { diff --git a/apps/dashboard/src/app/(app)/page.tsx b/apps/dashboard/src/app/(app)/page.tsx index 86a03e2b..45907d65 100644 --- a/apps/dashboard/src/app/(app)/page.tsx +++ b/apps/dashboard/src/app/(app)/page.tsx @@ -1,27 +1,30 @@ // import { CreateOrganization } from '@clerk/nextjs'; import { LogoSquare } from '@/components/Logo'; -import { getCurrentOrganizations } from '@openpanel/db'; import { redirect } from 'next/navigation'; +import { getCurrentOrganizations, isWaitlistUserAccepted } from '@openpanel/db'; + import { CreateOrganization } from './create-organization'; export default async function Page() { const organizations = await getCurrentOrganizations(); - if (process.env.BLOCK) { - return ( -
-
- -

Not quite there yet

-
- We're still working on Openpanel, but we're not quite there yet. - We'll let you know when we're ready to go! + const isAccepted = await isWaitlistUserAccepted(); + if (!isAccepted) { + return ( +
+
+ +

Not quite there yet

+
+ We're still working on Openpanel, but we're not quite there yet. + We'll let you know when we're ready to go! +
-
- ); + ); + } } if (organizations.length > 0) { diff --git a/apps/docs/Dockerfile b/apps/docs/Dockerfile index 35198283..bf8f42bf 100644 --- a/apps/docs/Dockerfile +++ b/apps/docs/Dockerfile @@ -1,35 +1,5 @@ FROM --platform=linux/amd64 node:20-slim AS base -ARG NEXT_PUBLIC_DASHBOARD_URL -ENV NEXT_PUBLIC_DASHBOARD_URL=$NEXT_PUBLIC_DASHBOARD_URL - -ARG NEXT_PUBLIC_API_URL -ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL - -ARG DATABASE_URL -ENV DATABASE_URL=$DATABASE_URL - -ARG CLICKHOUSE_DB -ENV CLICKHOUSE_DB=$CLICKHOUSE_DB - -ARG CLICKHOUSE_PASSWORD -ENV CLICKHOUSE_PASSWORD=$CLICKHOUSE_PASSWORD - -ARG CLICKHOUSE_URL -ENV CLICKHOUSE_URL=$CLICKHOUSE_URL - -ARG CLICKHOUSE_USER -ENV CLICKHOUSE_USER=$CLICKHOUSE_USER - -ARG REDIS_URL -ENV REDIS_URL=$REDIS_URL - -ARG NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY -ENV NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=$NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY - -ARG CLERK_SECRET_KEY -ENV CLERK_SECRET_KEY=$CLERK_SECRET_KEY - ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" @@ -50,14 +20,7 @@ WORKDIR /app COPY package.json package.json COPY pnpm-lock.yaml pnpm-lock.yaml COPY pnpm-workspace.yaml pnpm-workspace.yaml -COPY apps/public/package.json apps/public/package.json -COPY packages/db/package.json packages/db/package.json -COPY packages/redis/package.json packages/redis/package.json -COPY packages/queue/package.json packages/queue/package.json -COPY packages/common/package.json packages/common/package.json -COPY packages/constants/package.json packages/constants/package.json -COPY packages/validation/package.json packages/validation/package.json -COPY packages/sdk/package.json packages/sdk/package.json +COPY apps/docs/package.json apps/docs/package.json # BUILD FROM base AS build @@ -67,9 +30,8 @@ RUN pnpm install --frozen-lockfile --ignore-scripts WORKDIR /app COPY apps apps -COPY packages packages +RUN mkdir packages COPY tooling tooling -RUN pnpm db:codegen WORKDIR /app/apps/public RUN pnpm run build @@ -86,27 +48,11 @@ FROM base AS runner COPY --from=build /app/package.json /app/package.json COPY --from=prod /app/node_modules /app/node_modules # Apps -COPY --from=build /app/apps/public /app/apps/public +COPY --from=build /app/apps/docs /app/apps/docs # Apps node_modules -COPY --from=prod /app/apps/public/node_modules /app/apps/public/node_modules -# Packages -COPY --from=build /app/packages/db /app/packages/db -COPY --from=build /app/packages/redis /app/packages/redis -COPY --from=build /app/packages/common /app/packages/common -COPY --from=build /app/packages/queue /app/packages/queue -COPY --from=build /app/packages/constants /app/packages/constants -COPY --from=build /app/packages/validation /app/packages/validation -COPY --from=build /app/packages/sdk /app/packages/sdk -# Packages node_modules -COPY --from=prod /app/packages/db/node_modules /app/packages/db/node_modules -COPY --from=prod /app/packages/redis/node_modules /app/packages/redis/node_modules -COPY --from=prod /app/packages/common/node_modules /app/packages/common/node_modules -COPY --from=prod /app/packages/queue/node_modules /app/packages/queue/node_modules -COPY --from=prod /app/packages/validation/node_modules /app/packages/validation/node_modules +COPY --from=prod /app/apps/docs/node_modules /app/apps/docs/node_modules -RUN pnpm db:codegen - -WORKDIR /app/apps/public +WORKDIR /app/apps/docs EXPOSE 3000 diff --git a/apps/docs/src/components/brand-logo.tsx b/apps/docs/src/components/brand-logo.tsx new file mode 100644 index 00000000..5c7d1057 --- /dev/null +++ b/apps/docs/src/components/brand-logo.tsx @@ -0,0 +1,15 @@ +interface Props { + src: string; + isDark?: boolean; +} +export function BrandLogo({ src, isDark }: Props) { + if (isDark) { + return ( +
+ +
+ ); + } + + return ; +} diff --git a/apps/docs/src/pages/docs/_meta.json b/apps/docs/src/pages/docs/_meta.json index 75350419..1f71ac39 100644 --- a/apps/docs/src/pages/docs/_meta.json +++ b/apps/docs/src/pages/docs/_meta.json @@ -1,14 +1,21 @@ { "index": "Get Started", - "-- Implementation": { + "-- Frameworks": { "type": "separator", - "title": "Implementation" + "title": "Frameworks" }, "script": "Script", - "javascript": "Javascript SDK", "nextjs": "Next.js", "react": "React", "react-native": "React-Native", "remix": "Remix", - "vue": "Vue" + "vue": "Vue", + "astro": "Astro", + "node": "Node (backend)", + "-- Others": { + "type": "separator", + "title": "Others" + }, + "javascript": "Javascript SDK", + "web": "Web SDK" } diff --git a/apps/docs/src/pages/docs/astro.mdx b/apps/docs/src/pages/docs/astro.mdx new file mode 100644 index 00000000..3c22b8d3 --- /dev/null +++ b/apps/docs/src/pages/docs/astro.mdx @@ -0,0 +1,5 @@ +import Link from 'next/link'; + +# Astro + +You can use script tag or Web SDK to track events in Astro. diff --git a/apps/docs/src/pages/docs/index.mdx b/apps/docs/src/pages/docs/index.mdx index 464c5565..56e001a2 100644 --- a/apps/docs/src/pages/docs/index.mdx +++ b/apps/docs/src/pages/docs/index.mdx @@ -1,4 +1,5 @@ import { Card, Cards } from 'nextra/components'; +import { BrandLogo } from 'src/components/brand-logo'; # Get started @@ -7,22 +8,16 @@ Create an account on [Openpanel](https://openpanel.dev) and setup your first pro + } - title="General / Script" - href="/docs/general" + title="HTML / Script" + href="/docs/script" > {' '} + } title="React" href="/docs/react" @@ -31,10 +26,7 @@ Create an account on [Openpanel](https://openpanel.dev) and setup your first pro + } title="React-Native" href="/docs/react-native" @@ -43,8 +35,8 @@ Create an account on [Openpanel](https://openpanel.dev) and setup your first pro } @@ -55,8 +47,8 @@ Create an account on [Openpanel](https://openpanel.dev) and setup your first pro } @@ -67,14 +59,23 @@ Create an account on [Openpanel](https://openpanel.dev) and setup your first pro + } title="Vue" href="/docs/vue" > {' '} + + } + title="Astro" + href="/docs/vue" + > + {' '} + diff --git a/apps/docs/src/pages/docs/javascript.mdx b/apps/docs/src/pages/docs/javascript.mdx index 3069d40b..e7f85066 100644 --- a/apps/docs/src/pages/docs/javascript.mdx +++ b/apps/docs/src/pages/docs/javascript.mdx @@ -7,7 +7,7 @@ import SdkConfig from 'src/components/sdk-config.mdx'; # Javascript SDK -This is the base SDK for Openpanel. All other SDKs are built on top of this one. +This is the base SDK for Openpanel. All other SDKs/frameworks are built on top of this one. ## Installation @@ -21,9 +21,9 @@ pnpm install @openpanel/sdk ### Initialize ```tsx -import { Openpanel } from '@openpanel/sdk'; +import { OpenpanelSdk } from '@openpanel/sdk'; -const op = new Openpanel({ +const op = new OpenpanelSdk({ url: 'https://api.openpanel.dev', clientId: '{YOUR_CLIENT_ID}', // mostly for backend and apps that can't rely on CORS @@ -84,10 +84,8 @@ Keep track of your users by identifying them with a unique id. This is a good fe ```typescript -import { setProfileId } from '@openpanel/nextjs'; - const profileId = '123'; -setProfileId(profileId); +op.setProfileId(profileId); ``` #### Additional data @@ -97,10 +95,8 @@ This method does the same as `setProfileId` but also allows you to update the pr ```typescript -import { setProfile } from '@openpanel/nextjs'; - const profileId = '123'; -setProfile({ +op.setProfile({ profileId, // firstName?: string; // lastName?: string; @@ -115,13 +111,11 @@ setProfile({ Increment a property on the profile. ```typescript -import { increment } from '@openpanel/nextjs'; - // Increment by 1 -increment('app_opened'); +op.increment('app_opened'); // Increment by 5 -increment('app_opened', 5); +op.increment('app_opened', 5); ``` #### Decrement property @@ -129,11 +123,17 @@ increment('app_opened', 5); Decrement a property on the profile. ```typescript -import { decrement } from '@openpanel/nextjs'; - // Increment by 1 -decrement('app_opened'); +op.decrement('app_opened'); // Increment by 5 -decrement('app_opened', 5); +op.decrement('app_opened', 5); +``` + +#### Clear / Logout + +Clear the profile id and all the data. + +```typescript +op.clear(); ``` diff --git a/apps/docs/src/pages/docs/nextjs.mdx b/apps/docs/src/pages/docs/nextjs.mdx index 10e82fe3..494a3453 100644 --- a/apps/docs/src/pages/docs/nextjs.mdx +++ b/apps/docs/src/pages/docs/nextjs.mdx @@ -7,7 +7,9 @@ import SdkConfig from 'src/components/sdk-config.mdx'; # Next.js -Keep in mind that all tracking here happens on the client! If you want to track server-side events, you should use the node SDK 👀. +Keep in mind that all tracking here happens on the client! + +Read more about server side tracking in the [Server Side Tracking](#track-server-events) section. ## Installation @@ -170,3 +172,32 @@ decrement('app_opened'); // Increment by 5 decrement('app_opened', 5); ``` + +#### Clear / Logout + +Clear the profile id and all the data. + +```typescript +import { clear } from '@openpanel/nextjs'; + +clear(); +``` + +### Track server events + +If you want to track server-side events, you should create an instance of our Javascript SDK. It's exported from `@openpanel/nextjs` + +```typescript +import { OpenpanelSdk } from '@openpanel/nextjs'; + +const opServer = new OpenpanelSdk({ + url: 'https://api.openpanel.dev', + clientId: '{YOUR_CLIENT_ID}', + clientSecret: '{YOUR_CLIENT_SECRET}', +}); + +opServer.event('my_server_event', { ok: '✅' }); + +// Pass `profileId` to track events for a specific user +opServer.event('my_server_event', { profileId: '123', ok: '✅' }); +``` diff --git a/apps/docs/src/pages/docs/node.mdx b/apps/docs/src/pages/docs/node.mdx new file mode 100644 index 00000000..7c7063c7 --- /dev/null +++ b/apps/docs/src/pages/docs/node.mdx @@ -0,0 +1,5 @@ +import Link from 'next/link'; + +# Node + +Use Javascript SDK to track events in Node. diff --git a/apps/docs/src/pages/docs/react-native.mdx b/apps/docs/src/pages/docs/react-native.mdx index e4ea54f5..1a103133 100644 --- a/apps/docs/src/pages/docs/react-native.mdx +++ b/apps/docs/src/pages/docs/react-native.mdx @@ -194,3 +194,11 @@ op.decrement('app_opened'); // Increment by 5 op.decrement('app_opened', 5); ``` + +#### Clear / Logout + +Clear the profile id and all the data. + +```typescript +op.clear(); +``` diff --git a/apps/docs/src/pages/docs/react.mdx b/apps/docs/src/pages/docs/react.mdx index 66bee19c..6b660228 100644 --- a/apps/docs/src/pages/docs/react.mdx +++ b/apps/docs/src/pages/docs/react.mdx @@ -2,4 +2,4 @@ import Link from 'next/link'; # React -Use script tag or Javascript SDK for now. We'll add a dedicated react sdk soon. +Use script tag or Web SDK for now. We'll add a dedicated react sdk soon. diff --git a/apps/docs/src/pages/docs/remix.mdx b/apps/docs/src/pages/docs/remix.mdx index 8b3221ce..7e34cd88 100644 --- a/apps/docs/src/pages/docs/remix.mdx +++ b/apps/docs/src/pages/docs/remix.mdx @@ -2,4 +2,4 @@ import Link from 'next/link'; # Remix -Use script tag or Javascript SDK for now. We'll add a dedicated react sdk soon. +Use script tag or Web SDK for now. We'll add a dedicated remix sdk soon. diff --git a/apps/docs/src/pages/docs/script.mdx b/apps/docs/src/pages/docs/script.mdx index d7f9c234..ba992857 100644 --- a/apps/docs/src/pages/docs/script.mdx +++ b/apps/docs/src/pages/docs/script.mdx @@ -104,6 +104,14 @@ window.op('decrement', 'app_opened'); window.op('decrement', 'app_opened', 5); ``` +#### Clear / Logout + +Clear the profile id and all the data. + +```typescript +window.op('clear'); +``` + ### Typescript Is your IDE mad at you for not using typescript? We got you covered. diff --git a/apps/docs/src/pages/docs/vue.mdx b/apps/docs/src/pages/docs/vue.mdx index e7de0406..dad0be92 100644 --- a/apps/docs/src/pages/docs/vue.mdx +++ b/apps/docs/src/pages/docs/vue.mdx @@ -2,4 +2,4 @@ import Link from 'next/link'; # Vue -Use script tag or Javascript SDK for now. We'll add a dedicated react sdk soon. +Use script tag or Web SDK for now. We'll add a dedicated react sdk soon. diff --git a/apps/docs/src/pages/docs/web.mdx b/apps/docs/src/pages/docs/web.mdx new file mode 100644 index 00000000..8f9b9b81 --- /dev/null +++ b/apps/docs/src/pages/docs/web.mdx @@ -0,0 +1,138 @@ +import Link from 'next/link'; +import { Callout, Steps, Tabs } from 'nextra/components'; +import { DeviceIdWarning } from 'src/components/device-id-warning'; +import { PersonalDataWarning } from 'src/components/personal-data-warning'; + +import SdkConfig from 'src/components/sdk-config.mdx'; + +# Web SDK + +This is a wrapper of Javascript SDK. It's a simple way to use the Openpanel SDK in your web application. + +## Installation + + +### Install dependencies + +```bash +pnpm install @openpanel/web +``` + +### Initialize + +```tsx +import { Openpanel } from '@openpanel/web'; + +const op = new Openpanel({ + url: 'https://api.openpanel.dev', + clientId: '{YOUR_CLIENT_ID}', + trackScreenViews: true, + // trackAttributes: true, + // trackOutgoingLinks: true, +}); +``` + +#### Config + + + +### Ready! + +You're now ready to use the library. + +```typescript +// Sends an event with payload foo: bar +op.event('my_event', { foo: 'bar' }); + +// Identify with profile id +op.setProfileId('123'); + +// or with additional data +op.setProfile({ + profileId: '123', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@openpanel.dev', +}); + +// Increment a property +op.increment('app_opened'); // increment by 1 +op.increment('app_opened', 5); // increment by 5 + +// Decrement a property +op.decrement('app_opened'); // decrement by 1 +op.decrement('app_opened', 5); // decrement by 5 +``` + + + +## Usage + +### Track event + +```typescript +op.event('my_event', { foo: 'bar' }); +``` + +### Identify + +#### Set Profile Id + +Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior. + + + +```typescript +const profileId = '123'; +op.setProfileId(profileId); +``` + +#### Additional data + +This method does the same as `setProfileId` but also allows you to update the profile with additional data. + + + +```typescript +const profileId = '123'; +op.setProfile({ + profileId, + // firstName?: string; + // lastName?: string; + // email?: string; + // avatar?: string; + // properties?: Record; +}); +``` + +#### Increment property + +Increment a property on the profile. + +```typescript +// Increment by 1 +op.increment('app_opened'); + +// Increment by 5 +op.increment('app_opened', 5); +``` + +#### Decrement property + +Decrement a property on the profile. + +```typescript +// Increment by 1 +op.decrement('app_opened'); + +// Increment by 5 +op.decrement('app_opened', 5); +``` + +#### Clear / Logout + +Clear the profile id and all the data. + +```typescript +op.clear(); +``` diff --git a/captain-definition-docs b/captain-definition-docs new file mode 100644 index 00000000..56436874 --- /dev/null +++ b/captain-definition-docs @@ -0,0 +1,4 @@ +{ + "schemaVersion": 2, + "dockerfilePath": "./apps/docs/Dockerfile" +} diff --git a/packages/db/prisma/migrations/20240311201118_add_accepted_to_waitinglist/migration.sql b/packages/db/prisma/migrations/20240311201118_add_accepted_to_waitinglist/migration.sql new file mode 100644 index 00000000..4d3ef305 --- /dev/null +++ b/packages/db/prisma/migrations/20240311201118_add_accepted_to_waitinglist/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "waitlist" ADD COLUMN "accepted" BOOLEAN NOT NULL DEFAULT false; diff --git a/packages/db/prisma/schema.prisma b/packages/db/prisma/schema.prisma index 815e63c5..1800d578 100644 --- a/packages/db/prisma/schema.prisma +++ b/packages/db/prisma/schema.prisma @@ -153,6 +153,7 @@ model Waitlist { email String @unique createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt + accepted Boolean @default(false) @@map("waitlist") } diff --git a/packages/db/src/services/user.service.ts b/packages/db/src/services/user.service.ts index a41815ce..8921fe1c 100644 --- a/packages/db/src/services/user.service.ts +++ b/packages/db/src/services/user.service.ts @@ -1,6 +1,8 @@ import { auth, clerkClient } from '@clerk/nextjs'; import type { User } from '@clerk/nextjs/dist/types/server'; +import { db } from '../prisma-client'; + export function transformUser(user: User) { return { name: `${user.firstName} ${user.lastName}`, @@ -22,3 +24,18 @@ export async function getCurrentUser() { export async function getUserById(id: string) { return clerkClient.users.getUser(id).then(transformUser); } + +export async function isWaitlistUserAccepted() { + const user = await getCurrentUser(); + const waitlist = await db.waitlist.findFirst({ + where: { + email: user?.email, + }, + }); + + if (!waitlist) { + return false; + } + + return waitlist.accepted; +} diff --git a/packages/sdks/nextjs/index.tsx b/packages/sdks/nextjs/index.tsx index 3b028e0b..36dc4a8e 100644 --- a/packages/sdks/nextjs/index.tsx +++ b/packages/sdks/nextjs/index.tsx @@ -2,12 +2,23 @@ import Script from 'next/script'; import type { OpenpanelEventOptions, - OpenpanelWebOptions, + OpenpanelOptions, PostEventPayload, UpdateProfilePayload, } from '@openpanel/web'; -const CDN_URL = 'http://localhost:3002/op.js'; +export * from '@openpanel/web'; + +const CDN_URL = 'https://openpanel.dev/op.js'; + +declare global { + interface Window { + op: { + q?: [string, ...any[]]; + (method: OpenpanelMethods, ...args: any[]): void; + }; + } +} type OpenpanelMethods = | 'ctor' @@ -19,7 +30,7 @@ type OpenpanelMethods = | 'clear'; declare global { - interface Window { + interface window { op: { q?: [string, ...any[]]; (method: OpenpanelMethods, ...args: any[]): void; @@ -27,7 +38,7 @@ declare global { } } -type OpenpanelProviderProps = OpenpanelWebOptions & { +type OpenpanelProviderProps = OpenpanelOptions & { profileId?: string; cdnUrl?: string; }; diff --git a/packages/sdks/nextjs/package.json b/packages/sdks/nextjs/package.json index 419e3b6b..8aa30759 100644 --- a/packages/sdks/nextjs/package.json +++ b/packages/sdks/nextjs/package.json @@ -4,13 +4,11 @@ "module": "index.ts", "scripts": { "build": "rm -rf dist && tsup", - "build-for-openpanel": "pnpm build && cp dist/cdn.global.js ../../apps/public/public/op.js && cp dist/cdn.global.js ../../apps/test/public/op.js", "lint": "eslint .", "format": "prettier --check \"**/*.{mjs,ts,md,json}\"", "typecheck": "tsc --noEmit" }, "dependencies": { - "@openpanel/sdk": "workspace:*", "@openpanel/web": "workspace:*" }, "peerDependencies": { @@ -20,6 +18,7 @@ "@openpanel/eslint-config": "workspace:*", "@openpanel/prettier-config": "workspace:*", "@openpanel/tsconfig": "workspace:*", + "@types/react": "^18.2.20", "eslint": "^8.48.0", "prettier": "^3.0.3", "tsup": "^7.2.0", diff --git a/packages/sdks/nextjs/tsconfig.json b/packages/sdks/nextjs/tsconfig.json index 337e4067..145f03d2 100644 --- a/packages/sdks/nextjs/tsconfig.json +++ b/packages/sdks/nextjs/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "@openpanel/tsconfig/base.json", "compilerOptions": { + "incremental": false, "outDir": "dist" } } diff --git a/packages/sdks/nextjs/tsup.config.ts b/packages/sdks/nextjs/tsup.config.ts index fed909b5..befb1075 100644 --- a/packages/sdks/nextjs/tsup.config.ts +++ b/packages/sdks/nextjs/tsup.config.ts @@ -4,6 +4,6 @@ import config from '@openpanel/tsconfig/tsup.config.json' assert { type: 'json' export default defineConfig({ ...(config as any), - entry: ['index.ts'], + entry: ['index.tsx'], format: ['cjs', 'esm'], }); diff --git a/packages/sdks/react-native/index.ts b/packages/sdks/react-native/index.ts index dc1d2eac..604a4873 100644 --- a/packages/sdks/react-native/index.ts +++ b/packages/sdks/react-native/index.ts @@ -2,13 +2,14 @@ import { AppState, Platform } from 'react-native'; import * as Application from 'expo-application'; import Constants from 'expo-constants'; -import type { OpenpanelOptions, PostEventPayload } from '@openpanel/sdk'; -import { Openpanel } from '@openpanel/sdk'; +import type { OpenpanelSdkOptions, PostEventPayload } from '@openpanel/sdk'; +import { OpenpanelSdk } from '@openpanel/sdk'; -type OpenpanelNativeOptions = OpenpanelOptions; +export * from '@openpanel/sdk'; +export type OpenpanelOptions = OpenpanelSdkOptions; -export class OpenpanelNative extends Openpanel { - constructor(options: OpenpanelNativeOptions) { +export class Openpanel extends OpenpanelSdk { + constructor(options: OpenpanelOptions) { super(options); this.api.headers['User-Agent'] = Constants.getWebViewUserAgentAsync(); diff --git a/packages/sdks/react-native/tsconfig.json b/packages/sdks/react-native/tsconfig.json index f742bf0a..145f03d2 100644 --- a/packages/sdks/react-native/tsconfig.json +++ b/packages/sdks/react-native/tsconfig.json @@ -1,6 +1,7 @@ { - "extends": "@openpanel/tsconfig/sdk.json", + "extends": "@openpanel/tsconfig/base.json", "compilerOptions": { + "incremental": false, "outDir": "dist" } } diff --git a/packages/sdks/react-native/tsup.config.ts b/packages/sdks/react-native/tsup.config.ts index 446d20ad..76b96e47 100644 --- a/packages/sdks/react-native/tsup.config.ts +++ b/packages/sdks/react-native/tsup.config.ts @@ -2,7 +2,4 @@ import { defineConfig } from 'tsup'; import config from '@openpanel/tsconfig/tsup.config.json' assert { type: 'json' }; -export default defineConfig({ - ...(config as any), - minify: false, -}); +export default defineConfig(config as any); diff --git a/packages/sdks/sdk/index.ts b/packages/sdks/sdk/index.ts index ac349042..0a33c853 100644 --- a/packages/sdks/sdk/index.ts +++ b/packages/sdks/sdk/index.ts @@ -1,5 +1,3 @@ -// NEW - export interface OpenpanelEventOptions { profileId?: string; } @@ -33,7 +31,7 @@ export interface DecrementProfilePayload { value: number; } -export interface OpenpanelOptions { +export interface OpenpanelSdkOptions { url: string; clientId: string; clientSecret?: string; @@ -127,7 +125,9 @@ function createApi(_url: string) { }; } -export class Openpanel { +export class OpenpanelSdk< + Options extends OpenpanelSdkOptions = OpenpanelSdkOptions, +> { public options: Options; public api: ReturnType; private state: OpenpanelState = { diff --git a/packages/sdks/sdk/profileId.txt b/packages/sdks/sdk/profileId.txt deleted file mode 100644 index 9edaca56..00000000 --- a/packages/sdks/sdk/profileId.txt +++ /dev/null @@ -1 +0,0 @@ -f97a3167-8dc6-4bed-923b-3d118c544006 \ No newline at end of file diff --git a/packages/sdks/sdk/tsconfig.json b/packages/sdks/sdk/tsconfig.json index f742bf0a..145f03d2 100644 --- a/packages/sdks/sdk/tsconfig.json +++ b/packages/sdks/sdk/tsconfig.json @@ -1,6 +1,7 @@ { - "extends": "@openpanel/tsconfig/sdk.json", + "extends": "@openpanel/tsconfig/base.json", "compilerOptions": { + "incremental": false, "outDir": "dist" } } diff --git a/packages/sdks/web/cdn.ts b/packages/sdks/web/cdn.ts index 94c9828a..2f456717 100644 --- a/packages/sdks/web/cdn.ts +++ b/packages/sdks/web/cdn.ts @@ -1,4 +1,4 @@ -import { OpenpanelWeb as Openpanel } from './index'; +import { Openpanel } from './index'; declare global { interface Window { diff --git a/packages/sdks/web/index.ts b/packages/sdks/web/index.ts index ff4d03b1..a42bf684 100644 --- a/packages/sdks/web/index.ts +++ b/packages/sdks/web/index.ts @@ -1,9 +1,9 @@ -import type { OpenpanelOptions, PostEventPayload } from '@openpanel/sdk'; -import { Openpanel } from '@openpanel/sdk'; +import type { OpenpanelSdkOptions, PostEventPayload } from '@openpanel/sdk'; +import { OpenpanelSdk } from '@openpanel/sdk'; export * from '@openpanel/sdk'; -export type OpenpanelWebOptions = OpenpanelOptions & { +export type OpenpanelOptions = OpenpanelSdkOptions & { trackOutgoingLinks?: boolean; trackScreenViews?: boolean; trackAttributes?: boolean; @@ -16,10 +16,10 @@ function toCamelCase(str: string) { ); } -export class OpenpanelWeb extends Openpanel { +export class Openpanel extends OpenpanelSdk { private lastPath = ''; - constructor(options: OpenpanelWebOptions) { + constructor(options: OpenpanelOptions) { super(options); if (!this.isServer()) { diff --git a/packages/sdks/web/tsconfig.json b/packages/sdks/web/tsconfig.json index f742bf0a..145f03d2 100644 --- a/packages/sdks/web/tsconfig.json +++ b/packages/sdks/web/tsconfig.json @@ -1,6 +1,7 @@ { - "extends": "@openpanel/tsconfig/sdk.json", + "extends": "@openpanel/tsconfig/base.json", "compilerOptions": { + "incremental": false, "outDir": "dist" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 274ae57f..24e01d91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -924,9 +924,6 @@ importers: packages/sdks/nextjs: dependencies: - '@openpanel/sdk': - specifier: workspace:* - version: link:../sdk '@openpanel/web': specifier: workspace:* version: link:../web @@ -943,6 +940,9 @@ importers: '@openpanel/tsconfig': specifier: workspace:* version: link:../../../tooling/typescript + '@types/react': + specifier: ^18.2.20 + version: 18.2.56 eslint: specifier: ^8.48.0 version: 8.56.0 @@ -1152,6 +1152,9 @@ importers: tooling/publish: dependencies: + arg: + specifier: ^5.0.2 + version: 5.0.2 semver: specifier: ^7.5.4 version: 7.6.0 diff --git a/tooling/publish/package.json b/tooling/publish/package.json index 77ee46f6..221aa058 100644 --- a/tooling/publish/package.json +++ b/tooling/publish/package.json @@ -10,6 +10,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { + "arg": "^5.0.2", "semver": "^7.5.4" }, "devDependencies": { diff --git a/tooling/publish/publish.ts b/tooling/publish/publish.ts index ef9e236f..8bb65a91 100644 --- a/tooling/publish/publish.ts +++ b/tooling/publish/publish.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ import { execSync } from 'node:child_process'; import fs from 'node:fs'; import path from 'node:path'; +import arg from 'arg'; import semver from 'semver'; const sdkPackages = ['sdk', 'react-native', 'web', 'nextjs']; @@ -24,14 +24,36 @@ function exit(message: string, error?: unknown) { process.exit(1); } -function main() { - const [version] = process.argv.slice(2); - - if (!version) { - return console.error('Missing version'); +function checkUncommittedChanges() { + try { + const changedFiles = execSync('git ls-files --exclude-standard --others') + .toString() + .trim(); + if (changedFiles !== '') { + throw new Error('Uncommitted changes'); + } + execSync('git diff HEAD --exit-code'); + console.log('✅ No uncommitted changes'); + } catch (error) { + exit('Uncommitted changes', error); } +} - if (!semver.valid(version)) { +function main() { + checkUncommittedChanges(); + + const args = arg({ + // Types + '--version': String, + '--test': Boolean, + // Aliases + '-v': '--version', + }); + + const version = args['--version']; + const test = args['--test']; + + if (version && !semver.valid(version)) { return console.error('Version is not valid'); } @@ -51,8 +73,10 @@ function main() { try { for (const name of sdkPackages) { - const pkgJson = require(workspacePath(`./packages/${name}/package.json`)); - savePackageJson(workspacePath(`./packages/${name}/package.json`), { + const pkgJson = require( + workspacePath(`./packages/sdks/${name}/package.json`) + ); + savePackageJson(workspacePath(`./packages/sdks/${name}/package.json`), { ...pkgJson, ...properties, dependencies: Object.entries(pkgJson.dependencies).reduce( @@ -82,14 +106,16 @@ function main() { console.log('✅ Built packages'); - try { - for (const name of sdkPackages) { - execSync('npm publish --access=public', { - cwd: workspacePath(`./packages/${name}`), - }); + if (!test) { + try { + for (const name of sdkPackages) { + execSync('npm publish --access=public', { + cwd: workspacePath(`./packages/sdks/${name}`), + }); + } + } catch (error) { + exit('Failed publish packages', error); } - } catch (error) { - exit('Failed publish packages', error); } console.log('✅ All done!'); diff --git a/tooling/typescript/sdk.json b/tooling/typescript/sdk.json deleted file mode 100644 index 4992b259..00000000 --- a/tooling/typescript/sdk.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "lib": ["ESNext", "DOM", "DOM.Iterable"], - "module": "esnext", - "target": "esnext", - "moduleResolution": "bundler", - "moduleDetection": "force", - "composite": false, - "strict": true, - "downlevelIteration": true, - "skipLibCheck": true, - "jsx": "react-jsx", - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "allowJs": true, - "allowImportingTsExtensions": false, - "noEmit": false - } -}