@showwhat/openfeature 1.0.1 → 2.1.0

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/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @showwhat/openfeature
2
2
 
3
- [OpenFeature](https://openfeature.dev/) provider for **showwhat** - use showwhat's rule engine through the standard OpenFeature Server SDK.
3
+ [OpenFeature](https://openfeature.dev/) provider for **showwhat**.
4
+
5
+ Bridge showwhat's rule engine to the standard OpenFeature Server SDK. Evaluate flags and config through OpenFeature clients using showwhat definitions.
4
6
 
5
7
  ## Installation
6
8
 
package/dist/index.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { Provider, EvaluationContext, ResolutionDetails, JsonValue } from '@openfeature/server-sdk';
2
- import { DefinitionReader, ConditionEvaluators, Logger, Context } from 'showwhat';
2
+ import { ShowWhatOptions, DefinitionReader, Dependencies, Logger, Context } from 'showwhat';
3
3
 
4
- type ShowwhatProviderOptions = {
4
+ type ShowwhatProviderOptions = Omit<ShowWhatOptions, "data"> & {
5
5
  data: DefinitionReader;
6
- evaluators?: ConditionEvaluators;
7
- logger?: Logger;
6
+ deps?: Dependencies;
8
7
  };
9
8
  declare class ShowwhatProvider implements Provider {
10
9
  #private;
package/dist/index.js CHANGED
@@ -76,29 +76,28 @@ function mapShowwhatError(error) {
76
76
  return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };
77
77
  }
78
78
  const message = error instanceof Error ? error.message : String(error);
79
- return { errorCode: ErrorCode.GENERAL, errorMessage: message };
79
+ return {
80
+ errorCode: ErrorCode.GENERAL,
81
+ errorMessage: message
82
+ };
80
83
  }
81
84
 
82
85
  // src/provider.ts
83
86
  var ShowwhatProvider = class {
84
87
  metadata = { name: "showwhat" };
85
88
  runsOn = "server";
86
- #data;
87
- #evaluators;
88
- #logger;
89
+ #options;
89
90
  constructor(options) {
90
- this.#data = options.data;
91
- this.#evaluators = options.evaluators;
92
- this.#logger = options.logger;
91
+ this.#options = options;
93
92
  }
94
93
  async initialize() {
95
- if (this.#data.load) {
96
- await this.#data.load();
94
+ if (this.#options.data.load) {
95
+ await this.#options.data.load();
97
96
  }
98
97
  }
99
98
  async onClose() {
100
- if (this.#data.close) {
101
- await this.#data.close();
99
+ if (this.#options.data.close) {
100
+ await this.#options.data.close();
102
101
  }
103
102
  }
104
103
  async resolveBooleanEvaluation(flagKey, defaultValue, context) {
@@ -124,18 +123,25 @@ var ShowwhatProvider = class {
124
123
  );
125
124
  }
126
125
  async #resolve(flagKey, defaultValue, evalCtx, typeGuard) {
127
- const ctx = toShowwhatContext(evalCtx, this.#logger);
126
+ const ctx = toShowwhatContext(evalCtx, this.#options.logger);
128
127
  try {
129
- const resolution = await showwhat({
130
- key: flagKey,
128
+ const results = await showwhat({
129
+ keys: [flagKey],
131
130
  context: ctx,
132
- options: {
133
- data: this.#data,
134
- evaluators: this.#evaluators,
135
- logger: this.#logger
136
- }
131
+ deps: this.#options.deps,
132
+ options: this.#options
137
133
  });
138
- const value = resolution.value;
134
+ const entry = results[flagKey];
135
+ if (!entry.success) {
136
+ const mapped = mapShowwhatError(entry.error);
137
+ return {
138
+ value: defaultValue,
139
+ reason: StandardResolutionReasons.ERROR,
140
+ errorCode: mapped.errorCode,
141
+ errorMessage: mapped.errorMessage
142
+ };
143
+ }
144
+ const value = entry.value;
139
145
  if (!typeGuard(value)) {
140
146
  return {
141
147
  value: defaultValue,
@@ -144,10 +150,10 @@ var ShowwhatProvider = class {
144
150
  errorMessage: `Flag "${flagKey}" resolved to ${typeof value}, expected a compatible type`
145
151
  };
146
152
  }
147
- const hasConditions = resolution.meta.variation.conditionCount > 0;
153
+ const hasConditions = entry.meta.variation.conditionCount > 0;
148
154
  return {
149
155
  value,
150
- variant: resolution.meta.variation.id ?? String(resolution.meta.variation.index),
156
+ variant: entry.meta.variation.id ?? String(entry.meta.variation.index),
151
157
  reason: hasConditions ? StandardResolutionReasons.TARGETING_MATCH : StandardResolutionReasons.STATIC
152
158
  };
153
159
  } catch (error) {
@@ -162,10 +168,15 @@ var ShowwhatProvider = class {
162
168
  }
163
169
  };
164
170
  function isJsonValue(value) {
165
- if (value === null) return true;
166
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
171
+ if (value === null) {
167
172
  return true;
168
- if (Array.isArray(value)) return value.every(isJsonValue);
173
+ }
174
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
175
+ return true;
176
+ }
177
+ if (Array.isArray(value)) {
178
+ return value.every(isJsonValue);
179
+ }
169
180
  if (typeof value === "object") {
170
181
  return Object.values(value).every(isJsonValue);
171
182
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider.ts","../src/context.ts","../src/errors.ts"],"sourcesContent":["import type {\n EvaluationContext,\n JsonValue,\n Provider,\n ResolutionDetails,\n} from \"@openfeature/server-sdk\";\nimport { ErrorCode, StandardResolutionReasons } from \"@openfeature/server-sdk\";\nimport type { ConditionEvaluators, DefinitionReader, Logger } from \"showwhat\";\nimport { showwhat } from \"showwhat\";\nimport { toShowwhatContext } from \"./context.js\";\nimport { mapShowwhatError } from \"./errors.js\";\n\nexport type ShowwhatProviderOptions = {\n data: DefinitionReader;\n evaluators?: ConditionEvaluators;\n logger?: Logger;\n};\n\nexport class ShowwhatProvider implements Provider {\n readonly metadata = { name: \"showwhat\" } as const;\n readonly runsOn = \"server\" as const;\n\n #data: DefinitionReader;\n #evaluators: ConditionEvaluators | undefined;\n #logger: Logger | undefined;\n\n constructor(options: ShowwhatProviderOptions) {\n this.#data = options.data;\n this.#evaluators = options.evaluators;\n this.#logger = options.logger;\n }\n\n async initialize(): Promise<void> {\n if (this.#data.load) {\n await this.#data.load();\n }\n }\n\n async onClose(): Promise<void> {\n if (this.#data.close) {\n await this.#data.close();\n }\n }\n\n async resolveBooleanEvaluation(\n flagKey: string,\n defaultValue: boolean,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<boolean>> {\n return this.#resolve(\n flagKey,\n defaultValue,\n context,\n (v): v is boolean => typeof v === \"boolean\",\n );\n }\n\n async resolveStringEvaluation(\n flagKey: string,\n defaultValue: string,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<string>> {\n return this.#resolve(flagKey, defaultValue, context, (v): v is string => typeof v === \"string\");\n }\n\n async resolveNumberEvaluation(\n flagKey: string,\n defaultValue: number,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<number>> {\n return this.#resolve(flagKey, defaultValue, context, (v): v is number => typeof v === \"number\");\n }\n\n async resolveObjectEvaluation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<T>> {\n return this.#resolve(\n flagKey,\n defaultValue,\n context,\n isJsonValue as (value: unknown) => value is T,\n );\n }\n\n async #resolve<T>(\n flagKey: string,\n defaultValue: T,\n evalCtx: EvaluationContext,\n typeGuard: (value: unknown) => value is T,\n ): Promise<ResolutionDetails<T>> {\n const ctx = toShowwhatContext(evalCtx, this.#logger);\n\n try {\n const resolution = await showwhat({\n key: flagKey,\n context: ctx,\n options: {\n data: this.#data,\n evaluators: this.#evaluators,\n logger: this.#logger,\n },\n });\n\n const value = resolution.value;\n\n if (!typeGuard(value)) {\n return {\n value: defaultValue,\n reason: StandardResolutionReasons.ERROR,\n errorCode: ErrorCode.TYPE_MISMATCH,\n errorMessage: `Flag \"${flagKey}\" resolved to ${typeof value}, expected a compatible type`,\n };\n }\n\n const hasConditions = resolution.meta.variation.conditionCount > 0;\n\n return {\n value,\n variant: resolution.meta.variation.id ?? String(resolution.meta.variation.index),\n reason: hasConditions\n ? StandardResolutionReasons.TARGETING_MATCH\n : StandardResolutionReasons.STATIC,\n };\n } catch (error: unknown) {\n const mapped = mapShowwhatError(error);\n return {\n value: defaultValue,\n reason: StandardResolutionReasons.ERROR,\n errorCode: mapped.errorCode,\n errorMessage: mapped.errorMessage,\n };\n }\n }\n}\n\nfunction isJsonValue(value: unknown): value is JsonValue {\n if (value === null) return true;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\")\n return true;\n if (Array.isArray(value)) return value.every(isJsonValue);\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>).every(isJsonValue);\n }\n return false;\n}\n","import type { EvaluationContext, EvaluationContextValue } from \"@openfeature/server-sdk\";\nimport type { Context, ContextValue, Logger } from \"showwhat\";\nimport { noopLogger } from \"showwhat\";\n\n/**\n * Converts an OpenFeature EvaluationContextValue to a showwhat ContextValue.\n *\n * Primitives, primitive arrays, and nested objects of primitives are preserved.\n * Date and null values are not representable in JSON/YAML and are dropped.\n */\nfunction convertValue(value: EvaluationContextValue): ContextValue | undefined {\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const result: (string | number | boolean)[] = [];\n for (const item of value) {\n if (typeof item === \"string\" || typeof item === \"number\" || typeof item === \"boolean\") {\n result.push(item);\n } else {\n return undefined;\n }\n }\n return result;\n }\n\n if (value !== null && typeof value === \"object\" && !(value instanceof Date)) {\n const result: Record<string, ContextValue> = {};\n for (const [k, v] of Object.entries(value)) {\n const converted = convertValue(v);\n if (converted === undefined) {\n return undefined;\n }\n result[k] = converted;\n }\n return result;\n }\n\n return undefined;\n}\n\n/**\n * Converts an OpenFeature EvaluationContext into a showwhat Context.\n *\n * Primitives, primitive arrays, and nested objects of primitives are preserved.\n * Date and null values are dropped with a warning.\n */\nexport function toShowwhatContext(evalCtx: EvaluationContext, logger?: Logger): Context {\n const log = logger ?? noopLogger;\n const ctx: Context = {};\n\n for (const [key, value] of Object.entries(evalCtx)) {\n const converted = convertValue(value);\n if (converted !== undefined) {\n ctx[key] = converted;\n } else {\n log.warn(\"dropped unsupported context key\", { key });\n }\n }\n\n return ctx;\n}\n","import { ErrorCode } from \"@openfeature/server-sdk\";\nimport {\n DefinitionNotFoundError,\n DefinitionInactiveError,\n VariationNotFoundError,\n ValidationError,\n DataError,\n ShowwhatError,\n} from \"showwhat\";\n\ntype ErrorMapping = {\n errorCode: ErrorCode;\n errorMessage: string;\n};\n\nexport function mapShowwhatError(error: unknown): ErrorMapping {\n if (error instanceof DefinitionNotFoundError) {\n return { errorCode: ErrorCode.FLAG_NOT_FOUND, errorMessage: error.message };\n }\n\n if (error instanceof DefinitionInactiveError) {\n return { errorCode: ErrorCode.FLAG_NOT_FOUND, errorMessage: error.message };\n }\n\n if (error instanceof VariationNotFoundError) {\n return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };\n }\n\n if (error instanceof ValidationError) {\n return { errorCode: ErrorCode.INVALID_CONTEXT, errorMessage: error.message };\n }\n\n if (error instanceof DataError) {\n return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };\n }\n\n if (error instanceof ShowwhatError) {\n return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n return { errorCode: ErrorCode.GENERAL, errorMessage: message };\n}\n"],"mappings":"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","names":["ErrorCode","ErrorCode"]}
1
+ {"version":3,"sources":["../src/provider.ts","../src/context.ts","../src/errors.ts"],"sourcesContent":["import type {\n EvaluationContext,\n JsonValue,\n Provider,\n ResolutionDetails,\n} from \"@openfeature/server-sdk\";\nimport { ErrorCode, StandardResolutionReasons } from \"@openfeature/server-sdk\";\nimport type { DefinitionReader, Dependencies, ShowWhatOptions } from \"showwhat\";\nimport { showwhat } from \"showwhat\";\nimport { toShowwhatContext } from \"./context.js\";\nimport { mapShowwhatError } from \"./errors.js\";\n\nexport type ShowwhatProviderOptions = Omit<ShowWhatOptions, \"data\"> & {\n data: DefinitionReader;\n deps?: Dependencies;\n};\n\nexport class ShowwhatProvider implements Provider {\n readonly metadata = { name: \"showwhat\" } as const;\n readonly runsOn = \"server\" as const;\n\n #options: ShowwhatProviderOptions;\n\n constructor(options: ShowwhatProviderOptions) {\n this.#options = options;\n }\n\n async initialize(): Promise<void> {\n if (this.#options.data.load) {\n await this.#options.data.load();\n }\n }\n\n async onClose(): Promise<void> {\n if (this.#options.data.close) {\n await this.#options.data.close();\n }\n }\n\n async resolveBooleanEvaluation(\n flagKey: string,\n defaultValue: boolean,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<boolean>> {\n return this.#resolve(\n flagKey,\n defaultValue,\n context,\n (v): v is boolean => typeof v === \"boolean\",\n );\n }\n\n async resolveStringEvaluation(\n flagKey: string,\n defaultValue: string,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<string>> {\n return this.#resolve(flagKey, defaultValue, context, (v): v is string => typeof v === \"string\");\n }\n\n async resolveNumberEvaluation(\n flagKey: string,\n defaultValue: number,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<number>> {\n return this.#resolve(flagKey, defaultValue, context, (v): v is number => typeof v === \"number\");\n }\n\n async resolveObjectEvaluation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n context: EvaluationContext,\n ): Promise<ResolutionDetails<T>> {\n return this.#resolve(\n flagKey,\n defaultValue,\n context,\n isJsonValue as (value: unknown) => value is T,\n );\n }\n\n async #resolve<T>(\n flagKey: string,\n defaultValue: T,\n evalCtx: EvaluationContext,\n typeGuard: (value: unknown) => value is T,\n ): Promise<ResolutionDetails<T>> {\n const ctx = toShowwhatContext(evalCtx, this.#options.logger);\n\n try {\n const results = await showwhat({\n keys: [flagKey],\n context: ctx,\n deps: this.#options.deps,\n options: this.#options,\n });\n\n const entry = results[flagKey];\n\n if (!entry.success) {\n const mapped = mapShowwhatError(entry.error);\n return {\n value: defaultValue,\n reason: StandardResolutionReasons.ERROR,\n errorCode: mapped.errorCode,\n errorMessage: mapped.errorMessage,\n };\n }\n\n const value = entry.value;\n\n if (!typeGuard(value)) {\n return {\n value: defaultValue,\n reason: StandardResolutionReasons.ERROR,\n errorCode: ErrorCode.TYPE_MISMATCH,\n errorMessage: `Flag \"${flagKey}\" resolved to ${typeof value}, expected a compatible type`,\n };\n }\n\n const hasConditions = entry.meta.variation.conditionCount > 0;\n\n return {\n value,\n variant: entry.meta.variation.id ?? String(entry.meta.variation.index),\n reason: hasConditions\n ? StandardResolutionReasons.TARGETING_MATCH\n : StandardResolutionReasons.STATIC,\n };\n } catch (error: unknown) {\n const mapped = mapShowwhatError(error);\n return {\n value: defaultValue,\n reason: StandardResolutionReasons.ERROR,\n errorCode: mapped.errorCode,\n errorMessage: mapped.errorMessage,\n };\n }\n }\n}\n\nfunction isJsonValue(value: unknown): value is JsonValue {\n if (value === null) {\n return true;\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(isJsonValue);\n }\n\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>).every(isJsonValue);\n }\n\n return false;\n}\n","import type { EvaluationContext, EvaluationContextValue } from \"@openfeature/server-sdk\";\nimport type { Context, ContextValue, Logger } from \"showwhat\";\nimport { noopLogger } from \"showwhat\";\n\n/**\n * Converts an OpenFeature EvaluationContextValue to a showwhat ContextValue.\n *\n * Primitives, primitive arrays, and nested objects of primitives are preserved.\n * Date and null values are not representable in JSON/YAML and are dropped.\n */\nfunction convertValue(value: EvaluationContextValue): ContextValue | undefined {\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const result: (string | number | boolean)[] = [];\n for (const item of value) {\n if (typeof item === \"string\" || typeof item === \"number\" || typeof item === \"boolean\") {\n result.push(item);\n } else {\n return undefined;\n }\n }\n\n return result;\n }\n\n if (value !== null && typeof value === \"object\" && !(value instanceof Date)) {\n const result: Record<string, ContextValue> = {};\n for (const [k, v] of Object.entries(value)) {\n const converted = convertValue(v);\n\n if (converted === undefined) {\n return undefined;\n }\n\n result[k] = converted;\n }\n return result;\n }\n\n return undefined;\n}\n\n/**\n * Converts an OpenFeature EvaluationContext into a showwhat Context.\n *\n * Primitives, primitive arrays, and nested objects of primitives are preserved.\n * Date and null values are dropped with a warning.\n */\nexport function toShowwhatContext(evalCtx: EvaluationContext, logger?: Logger): Context {\n const log = logger ?? noopLogger;\n const ctx: Context = {};\n\n for (const [key, value] of Object.entries(evalCtx)) {\n const converted = convertValue(value);\n\n if (converted !== undefined) {\n ctx[key] = converted;\n } else {\n log.warn(\"dropped unsupported context key\", { key });\n }\n }\n\n return ctx;\n}\n","import { ErrorCode } from \"@openfeature/server-sdk\";\nimport {\n DefinitionNotFoundError,\n DefinitionInactiveError,\n VariationNotFoundError,\n ValidationError,\n DataError,\n ShowwhatError,\n} from \"showwhat\";\n\ntype ErrorMapping = {\n errorCode: ErrorCode;\n errorMessage: string;\n};\n\nexport function mapShowwhatError(error: unknown): ErrorMapping {\n if (error instanceof DefinitionNotFoundError) {\n return { errorCode: ErrorCode.FLAG_NOT_FOUND, errorMessage: error.message };\n }\n\n if (error instanceof DefinitionInactiveError) {\n return { errorCode: ErrorCode.FLAG_NOT_FOUND, errorMessage: error.message };\n }\n\n if (error instanceof VariationNotFoundError) {\n return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };\n }\n\n if (error instanceof ValidationError) {\n return { errorCode: ErrorCode.INVALID_CONTEXT, errorMessage: error.message };\n }\n\n if (error instanceof DataError) {\n return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };\n }\n\n if (error instanceof ShowwhatError) {\n return { errorCode: ErrorCode.GENERAL, errorMessage: error.message };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n\n return {\n errorCode: ErrorCode.GENERAL,\n errorMessage: message,\n };\n}\n"],"mappings":"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","names":["ErrorCode","ErrorCode"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@showwhat/openfeature",
3
- "version": "1.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "OpenFeature provider for showwhat library",
5
5
  "keywords": [
6
6
  "feature-flags",
@@ -35,18 +35,18 @@
35
35
  "dist"
36
36
  ],
37
37
  "dependencies": {
38
- "showwhat": "1.0.1"
38
+ "showwhat": "2.1.0"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@openfeature/server-sdk": "^1.0.0"
42
42
  },
43
43
  "devDependencies": {
44
- "@openfeature/server-sdk": "^1.20.0",
45
- "@types/node": "^25.4.0",
46
- "@vitest/coverage-v8": "^4.0.0",
47
- "tsup": "^8.0.0",
48
- "typescript": "^5.4.0",
49
- "vitest": "^4.0.0"
44
+ "@openfeature/server-sdk": "^1.20.2",
45
+ "@types/node": "^25.5.0",
46
+ "@vitest/coverage-v8": "^4.1.4",
47
+ "tsup": "^8.5.1",
48
+ "typescript": "^5.9.3",
49
+ "vitest": "^4.1.4"
50
50
  },
51
51
  "scripts": {
52
52
  "build": "tsup",