Code Monkey home page Code Monkey logo

configcat / js-ssr-sdk Goto Github PK

View Code? Open in Web Editor NEW
12.0 12.0 6.0 1.89 MB

ConfigCat SDK for JavaScript Server Side Rendered applications like NuxtJS. ConfigCat is a hosted feature flag service: https://configcat.com. Manage feature toggles across frontend, backend, mobile, desktop apps. Alternative to LaunchDarkly. Management app + feature flag SDKs.

Home Page: https://configcat.com/docs/sdk-reference/js-ssr

License: MIT License

Shell 0.74% JavaScript 12.99% TypeScript 86.27%
configcat-sdk feature-flags feature-management feature-toggle javascript nuxtjs remote-config sdk server-side-rendering ssr

js-ssr-sdk's People

Contributors

adams85 avatar dependabot[bot] avatar endret avatar jlongman avatar kp-cat avatar lajos88 avatar laliconfigcat avatar luckened avatar sigewuzhere avatar z4kn4fein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

js-ssr-sdk's Issues

Integrate SSR with React

Is your feature request related to a problem? Please describe.

There are three configcat JS libraries, and the advantage of the SSR one over Node.js or React isn't clear. In my case, I'm using Remix, and the user ID is entirely on the server within the cookie derived session. I need the React.js render to match on both the server and client side.

Describe the solution you'd like

I would like a set of React components that can take the ConfigCat values passed from a server route loader and initialize the context of the react components.

Describe alternatives you've considered

I considered the react library, but like I mentioned, the client-side doesn't have a copy of the user-id. Passing it would expose the app to unnecessary data leakage.

I considered the Node.js library, but I didn't see the differences spelled out. While I'm running Remix on Node.js, it could run on other JavaScript engines like Cloudflare Workers.

Using the SSR library to as documented doesn't provide a clear way to optionally render UI components in a consistent manner between the server and client. I need the server to get the flags for the logged-in user and then both use them when rendering to HTML and distribute the settings to the client so it can also use the values while rendering.

Additional context

I wrote two files to aid me in this:

configcat.server.ts:

import type { SettingKeyValue } from "configcat-js-ssr";
import {
  createConsoleLogger,
  getClient,
  LogLevel,
  PollingMode,
  User,
} from "configcat-js-ssr";
import { get_process_env } from "~/utils";

const sdkKey = get_process_env("CONFIGCAT_SDK_KEY");

const configCatClient = getClient(sdkKey, PollingMode.AutoPoll);

export async function getConfigCatValues(
  identifier: string
): Promise<SettingKeyValue[]> {
  const userObject = new User(identifier);
  const settingValues = await configCatClient.getAllValuesAsync(userObject);
  return settingValues;
}

and configcat.tsx:

import type { ReactNode } from "react";
import { createContext, useContext } from "react";

import type { SettingValue } from "configcat-js-ssr";

import { getLogger } from "~/services/logging";

const logger = getLogger("configcat");

/**
 * Remix loader compatible type for ConfigCat SettingKeyValue
 */
interface SettingKeyValue {
  settingKey: string;
  settingValue?: SettingValue;
}

const ConfigCatContext = createContext<SettingKeyValue[]>([]);

export function useConfigCat(): SettingKeyValue[] {
  return useContext(ConfigCatContext);
}

export function useFeatureFlag<T extends SettingValue>(
  key: string,
  defaultValue: T
): T {
  const typeofDefaultValue = typeof defaultValue;
  if (
    defaultValue != null &&
    ["boolean", "number", "string"].indexOf(typeofDefaultValue) === -1
  ) {
    throw new TypeError(
      `Invalid type for 'defaultValue': ${typeofDefaultValue}`
    );
  }
  const context = useContext(ConfigCatContext);
  const settingValue = context.find((x) => x.settingKey === key)?.settingValue;
  if (settingValue == null) {
    return defaultValue;
  }

  if (typeof settingValue === typeofDefaultValue) {
    return settingValue as T;
  } else {
    console.error(
      `typeof of setting value (${typeof settingValue}) for setting '${key}' does not match type of defaultValue (${typeofDefaultValue})`
    );
  }

  return defaultValue;
}

export function ConfigCatProvider({
  children,
  value,
}: {
  children?: ReactNode | undefined;
  value: SettingKeyValue[];
}) {
  return (
    <ConfigCatContext.Provider value={value}>
      {children}
    </ConfigCatContext.Provider>
  );
}

And use like this:

export async function loader({ request }: LoaderArgs) {
  const session = await getSession(request.headers.get("Cookie"));
  const user = await requireAuthenticatedUser(request, session);
  const configCatValues = await getConfigCatValues(user.profile.username);

  const data: LoaderData = {
    configCatValues,
  };

  return json(data);
}

export default function Index() {
  const { configCatValues } = useLoaderData<typeof loader>();
}

  return (
    <ConfigCatProvider value={configCatValues}>
      <Outlet />
    </ConfigCatProvider>
  );
}

Switch from Axios to HTTP/HTTPS

I was reading through the ConfigCat Community Slack and was intrigued by the error someone was having which the investigation showed that Axios was the issue. I haven't looked too much into the code of this SDK but I believe it should be possible to swap from Axios to Node.js's build in HTTP/HTTPS libraries.

Import error with Next.js in production mode

Describe the bug

I have a Next application (v12.0.5) and I want to get the feature flags from Configcat on both server side and client side.

In development everything works as expected but the production version trigger this exception run-time:

TypeError: Cannot read properties of undefined (reading 'createClientWithAutoPoll')
    at createClient (/Users/redacted/redacted/IL.PE.PEP.Frontend/node_modules/.pnpm/[email protected]/node_modules/configcat-js-ssr/lib/index.js:12:17)
    at eval (webpack-internal:///./lib/configcat/index.ts:12:83)
    at Object../lib/configcat/index.ts (/Users/redacted/redacted/IL.PE.PEP.Frontend/platforms/teacher/.next/server/pages/_app.js:198:1)
    at __webpack_require__ (/Users/redacted/redacted/IL.PE.PEP.Frontend/platforms/teacher/.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///./pages/_app.page.tsx:12:72)
    at Function.__webpack_require__.a (/Users/redacted/redacted/IL.PE.PEP.Frontend/platforms/teacher/.next/server/webpack-runtime.js:106:13)
    at eval (webpack-internal:///./pages/_app.page.tsx:1:21)
    at Object../pages/_app.page.tsx (/Users/redacted/redacted/IL.PE.PEP.Frontend/platforms/teacher/.next/server/pages/_app.js:319:1)
    at __webpack_require__ (/Users/redacted/redacted/IL.PE.PEP.Frontend/platforms/teacher/.next/server/webpack-runtime.js:33:42)
    at __webpack_exec__ (/Users/redacted/redacted/IL.PE.PEP.Frontend/platforms/teacher/.next/server/pages/_app.js:1021:39)

To reproduce

Create a Next.js app and use the getAllValues below on both client and server side:

import * as configcat from "configcat-js-ssr";

const configCatClient = configcat.createClient(YOUR_KEY_HERE);

export const getAllValues = async () => {
  const settingValues = await configCatClient.getAllValuesAsync(userObject);
  return settingValues;
};

Expected behavior

It should work in development and production mode without errors.

Findings

The issue is related to the createClient function that internally uses a reference to this that is undefined. I managed to avoid the error using createClientWithAutoPoll instead of createClient.

I really suggest changing how this works internally or at least updating the readme to avoid an unpleasant surprise in production.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.