vue3-app-configuration
Version:
A Vue 3 plugin for integrating Azure App Configuration, including feature flags management.
1 lines • 11.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n AppConfigurationClient,\n featureFlagPrefix,\n isFeatureFlag,\n parseFeatureFlag,\n} from \"@azure/app-configuration\";\nimport { inject, reactive, ref, type App, type InjectionKey, type Ref } from \"vue\";\n\ntype FlagOptionsType = {\n name: string;\n label?: string;\n};\n\ntype GetFeatureFlagType = (params: FlagOptionsType) => {\n isFeatureEnabled: Ref<boolean>;\n featureDescription: Ref<string>;\n featureConditions: IConditions;\n};\n\ninterface IFeatureFlagsManager {\n appConfigurationClient: AppConfigurationClientType;\n getFeatureFlag: GetFeatureFlagType;\n}\n\ntype AppConfigurationClientType = AppConfigurationClient | null;\n\nconst FeatureFlagsManagerKey: InjectionKey<IFeatureFlagsManager> = Symbol(\n \"FeatureFlagsManager\"\n);\n\ninterface IConditions {\n clientFilters?: {\n name: string;\n parameters?: Record<string, unknown>;\n }[];\n}\n\ninterface IFeatureFlagCache {\n [key: string]: {\n isFeatureEnabled: Ref<boolean>;\n featureDescription: Ref<string>;\n featureConditions: IConditions;\n };\n}\n\nconst featureFlagsManager = (\n connectionString?: string,\n cacheEnabled = true,\n flagsToPrefetchOptmistic: FlagOptionsType[] = []\n): IFeatureFlagsManager => {\n let appConfigurationClient: AppConfigurationClientType = null;\n\n if (connectionString) {\n appConfigurationClient = new AppConfigurationClient(connectionString);\n }\n\n const cache: IFeatureFlagCache = {};\n\n function prefetchFeatureFlagsOptimistic(flags: FlagOptionsType[]) {\n if (!appConfigurationClient) {\n return;\n }\n for (const { name, label } of flags) {\n appConfigurationClient\n .getConfigurationSetting({\n key: `${featureFlagPrefix}${name}`,\n label,\n })\n .then((response) => {\n if (isFeatureFlag(response)) {\n const {\n value: { enabled, description = \"\", conditions },\n } = parseFeatureFlag(response);\n\n const cacheKey = `cache-${name}-${label ?? \"empty-label\"}`;\n\n cache[cacheKey] = {\n isFeatureEnabled: ref(enabled),\n featureDescription: ref(description),\n featureConditions: reactive({\n clientFilters: conditions.clientFilters ?? []\n })\n };\n }\n })\n .catch((error) => {\n console.error(\n \"[App Configuration Plugin] Error prefetching feature flag.\",\n error\n );\n });\n }\n }\n\n if (flagsToPrefetchOptmistic.length) {\n prefetchFeatureFlagsOptimistic(flagsToPrefetchOptmistic);\n }\n\n const getFeatureFlag: GetFeatureFlagType = ({ name, label }) => {\n const cacheKey = `cache-${name}-${label ?? \"empty-label\"}`;\n\n if (cacheEnabled && cache[cacheKey]) {\n return cache[cacheKey];\n }\n\n const isFeatureEnabled = ref(false);\n const featureDescription = ref(\"\");\n const featureConditions = reactive({})\n\n if (!appConfigurationClient) {\n if (cacheEnabled) {\n cache[cacheKey] = { isFeatureEnabled, featureDescription, featureConditions };\n }\n return { isFeatureEnabled, featureDescription, featureConditions };\n }\n\n appConfigurationClient\n .getConfigurationSetting({\n key: `${featureFlagPrefix}${name}`,\n label,\n })\n .then((response) => {\n if (isFeatureFlag(response)) {\n const {\n value: { enabled, description = \"\", conditions },\n } = parseFeatureFlag(response);\n\n isFeatureEnabled.value = enabled;\n featureDescription.value = description;\n Object.assign(conditions, featureConditions)\n\n if (cacheEnabled) {\n cache[cacheKey] = { isFeatureEnabled, featureDescription, featureConditions };\n }\n }\n })\n .catch((error) => {\n console.error(\n \"[App Configuration Plugin] Error retrieving feature flag.\",\n error\n );\n });\n\n return { isFeatureEnabled, featureDescription, featureConditions };\n };\n\n return { getFeatureFlag, appConfigurationClient };\n};\n\nconst featureFlagsManagerAsync = async (\n connectionString?: string,\n flagsToPrefetch: FlagOptionsType[] = []\n): Promise<IFeatureFlagsManager> => {\n let appConfigurationClient: AppConfigurationClientType = null;\n\n if (connectionString) {\n appConfigurationClient = new AppConfigurationClient(connectionString);\n }\n\n const cache: IFeatureFlagCache = {};\n\n async function prefetchFeatureFlags(flags: FlagOptionsType[]) {\n if (!appConfigurationClient) {\n return;\n }\n\n await Promise.all(\n flags.map(async ({ name, label }) => {\n try {\n const response =\n await appConfigurationClient!.getConfigurationSetting({\n key: `${featureFlagPrefix}${name}`,\n label,\n });\n\n if (isFeatureFlag(response)) {\n const {\n value: { enabled, description = \"\", conditions },\n } = parseFeatureFlag(response);\n\n const cacheKey = `cache-${name}-${label ?? \"empty-label\"}`;\n\n cache[cacheKey] = {\n isFeatureEnabled: ref(enabled),\n featureDescription: ref(description),\n featureConditions: reactive({\n clientFilters: conditions.clientFilters ?? []\n })\n };\n }\n } catch (error) {\n console.error(\n \"[App Configuration Plugin] Error prefetching feature flag.\",\n error\n );\n }\n })\n );\n }\n\n await prefetchFeatureFlags(flagsToPrefetch);\n\n const getFeatureFlag: GetFeatureFlagType = ({ name, label }) => {\n const cacheKey = `cache-${name}-${label ?? \"empty-label\"}`;\n\n if (cache[cacheKey]) {\n return cache[cacheKey];\n }\n\n cache[cacheKey] = {\n isFeatureEnabled: ref(false),\n featureDescription: ref(\"\"),\n featureConditions: reactive({\n clientFilters: []\n })\n };\n\n return cache[cacheKey];\n };\n\n return { getFeatureFlag, appConfigurationClient };\n};\n\nconst AppConfigurationPlugin = {\n install: (\n app: App,\n options: {\n connectionString?: string;\n cacheEnabled?: boolean;\n flagsToPrefetchOptmistic?: FlagOptionsType[];\n }\n ) => {\n const manager = featureFlagsManager(\n options.connectionString,\n options.cacheEnabled,\n options.flagsToPrefetchOptmistic\n );\n app.provide(FeatureFlagsManagerKey, manager);\n },\n};\n\nconst AppConfigurationPluginAsync = {\n _installPromise: null as Promise<void> | null,\n install: (\n app: App,\n options: { connectionString?: string; flagsToPrefetch?: FlagOptionsType[] }\n ) => {\n AppConfigurationPluginAsync._installPromise = new Promise<void>(\n async (resolve) => {\n const manager = await featureFlagsManagerAsync(\n options.connectionString,\n options.flagsToPrefetch\n );\n app.provide(FeatureFlagsManagerKey, manager);\n resolve();\n }\n );\n },\n isReady: (): Promise<void> =>\n AppConfigurationPluginAsync._installPromise || Promise.resolve(),\n};\n\nconst useFeatureFlags = () => {\n const featureFlagsManager = inject(FeatureFlagsManagerKey);\n if (!featureFlagsManager) {\n throw new Error(\n \"[App Configuration Plugin] FeatureFlagsManager is not provided.\"\n );\n }\n return featureFlagsManager;\n};\n\nexport { AppConfigurationPlugin, AppConfigurationPluginAsync, useFeatureFlags };\n"],"mappings":"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","names":["_0","featureFlagsManager"]}