showwhat 1.0.0 → 2.0.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
2
2
 
3
- Feature flag resolution engine the main entry point for **showwhat**, a lightweight, extensible feature flag library.
3
+ Feature flags and config you own. Platform-agnostic.
4
+
5
+ `showwhat` combines a YAML/JSON definition format with a schema-validated, extensible rule engine. Define flags and config as variations with conditions, evaluate them in your app, and store definitions wherever you want.
4
6
 
5
7
  ## Installation
6
8
 
@@ -27,25 +29,23 @@ const data = await MemoryData.fromObject({
27
29
  },
28
30
  });
29
31
 
30
- const result = await showwhat({
31
- key: "checkout_v2",
32
+ const results = await showwhat({
33
+ keys: ["checkout_v2"],
32
34
  context: { env: "prod" },
33
35
  options: { data },
34
36
  });
35
- console.log(result.value); // true
37
+ console.log(results.checkout_v2.value); // true
36
38
  ```
37
39
 
38
40
  ## Features
39
41
 
40
- - `showwhat()` resolution engine with context validation
42
+ - `showwhat()` resolution engine for flags and config values
41
43
  - Built-in condition evaluators: `string`, `number`, `datetime`, `bool`, `env`, `startAt`, `endAt`
42
44
  - Custom evaluators via `registerEvaluators()`
43
45
  - YAML and JSON parsing with schema validation
44
46
  - Pluggable data sources (`DefinitionReader` / `DefinitionWriter`)
45
47
  - Typed error hierarchy
46
48
 
47
- This package re-exports everything from `@showwhat/core`.
48
-
49
49
  ## Documentation
50
50
 
51
51
  - [Quick Start](https://showwhat.yeojz.dev/docs/) — installation and first definition
package/dist/index.d.ts CHANGED
@@ -1,14 +1,16 @@
1
- import { ResolverOptions, DefinitionReader, ConditionEvaluators, BuiltinCondition, Context, Resolution } from '@showwhat/core';
1
+ import { Resolution, ResolutionError, ResolverOptions, DefinitionReader, ConditionEvaluators, BuiltinCondition, ContextValue, Context, Dependencies } from '@showwhat/core';
2
2
  export * from '@showwhat/core';
3
3
 
4
4
  type ShowWhatOptions = ResolverOptions & {
5
5
  data: DefinitionReader;
6
6
  };
7
- declare function showwhat({ key, context, options, }: {
8
- key: string;
9
- context: Context;
7
+ type Resolutions = Record<string, Resolution | ResolutionError>;
8
+ declare function showwhat<T extends Record<string, ContextValue> = Record<string, ContextValue>, D extends Record<string, unknown> = Record<string, unknown>>({ keys, context, deps, options, }: {
9
+ keys?: string[];
10
+ context: Context<T>;
11
+ deps?: Dependencies<D>;
10
12
  options: ShowWhatOptions;
11
- }): Promise<Resolution>;
13
+ }): Promise<Resolutions>;
12
14
  declare function registerEvaluators<T extends string>(extra: ConditionEvaluators<T>): ConditionEvaluators<BuiltinCondition["type"] | T>;
13
15
 
14
- export { type ShowWhatOptions, registerEvaluators, showwhat };
16
+ export { type Resolutions, type ShowWhatOptions, registerEvaluators, showwhat };
package/dist/index.js CHANGED
@@ -2,14 +2,35 @@
2
2
  import {
3
3
  ContextSchema,
4
4
  builtinEvaluators,
5
- DefinitionNotFoundError,
6
5
  ValidationError,
6
+ DataError,
7
7
  resolve
8
8
  } from "@showwhat/core";
9
9
  export * from "@showwhat/core";
10
+ async function fetchDefinitions(data, keys) {
11
+ if (!keys) {
12
+ try {
13
+ return await data.getAll();
14
+ } catch (err) {
15
+ throw new DataError("Failed to fetch definitions", err);
16
+ }
17
+ }
18
+ const definitions = {};
19
+ await Promise.all(
20
+ keys.map(async (key) => {
21
+ try {
22
+ definitions[key] = await data.get(key);
23
+ } catch (err) {
24
+ throw new DataError(`Failed to fetch definition "${key}"`, err);
25
+ }
26
+ })
27
+ );
28
+ return definitions;
29
+ }
10
30
  async function showwhat({
11
- key,
31
+ keys,
12
32
  context,
33
+ deps,
13
34
  options
14
35
  }) {
15
36
  const contextResult = ContextSchema.safeParse(context);
@@ -19,21 +40,15 @@ async function showwhat({
19
40
  "context"
20
41
  );
21
42
  }
22
- const validatedContext = contextResult.data;
23
- const def = await options.data.get(key);
24
- if (!def) {
25
- throw new DefinitionNotFoundError(key);
26
- }
27
- const result = await resolve({
28
- definitions: { [key]: def },
29
- context: validatedContext,
43
+ return resolve({
44
+ definitions: await fetchDefinitions(options.data, keys),
45
+ context: contextResult.data,
46
+ deps,
30
47
  options: {
31
- evaluators: options.evaluators ?? builtinEvaluators,
32
- fallback: options.fallback,
33
- logger: options.logger
48
+ ...options,
49
+ evaluators: options.evaluators ?? builtinEvaluators
34
50
  }
35
51
  });
36
- return result[key];
37
52
  }
38
53
  var COMPOSITE_TYPES = /* @__PURE__ */ new Set(["and", "or"]);
39
54
  function registerEvaluators(extra) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n ContextSchema,\n builtinEvaluators,\n DefinitionNotFoundError,\n ValidationError,\n resolve,\n} from \"@showwhat/core\";\nimport type {\n BuiltinCondition,\n ConditionEvaluators,\n Context,\n DefinitionReader,\n Resolution,\n ResolverOptions,\n} from \"@showwhat/core\";\n\nexport * from \"@showwhat/core\";\n\nexport type ShowWhatOptions = ResolverOptions & {\n data: DefinitionReader;\n};\n\nexport async function showwhat({\n key,\n context,\n options,\n}: {\n key: string;\n context: Context;\n options: ShowWhatOptions;\n}): Promise<Resolution> {\n const contextResult = ContextSchema.safeParse(context);\n if (!contextResult.success) {\n throw new ValidationError(\n contextResult.error.issues.map((i) => `[${i.path.join(\".\")}] ${i.message}`).join(\"; \"),\n \"context\",\n );\n }\n\n const validatedContext = contextResult.data;\n const def = await options.data.get(key);\n\n if (!def) {\n throw new DefinitionNotFoundError(key);\n }\n\n const result = await resolve({\n definitions: { [key]: def },\n context: validatedContext,\n options: {\n evaluators: options.evaluators ?? builtinEvaluators,\n fallback: options.fallback,\n logger: options.logger,\n },\n });\n\n return result[key];\n}\n\nconst COMPOSITE_TYPES = new Set([\"and\", \"or\"]);\n\nexport function registerEvaluators<T extends string>(\n extra: ConditionEvaluators<T>,\n): ConditionEvaluators<BuiltinCondition[\"type\"] | T> {\n for (const key of Object.keys(extra)) {\n if (COMPOSITE_TYPES.has(key)) {\n throw new Error(`Cannot register reserved condition type \"${key}\"`);\n }\n }\n return { ...builtinEvaluators, ...extra };\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUP,cAAc;AAMd,eAAsB,SAAS;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAIwB;AACtB,QAAM,gBAAgB,cAAc,UAAU,OAAO;AACrD,MAAI,CAAC,cAAc,SAAS;AAC1B,UAAM,IAAI;AAAA,MACR,cAAc,MAAM,OAAO,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB,cAAc;AACvC,QAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,GAAG;AAEtC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,wBAAwB,GAAG;AAAA,EACvC;AAEA,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,aAAa,EAAE,CAAC,GAAG,GAAG,IAAI;AAAA,IAC1B,SAAS;AAAA,IACT,SAAS;AAAA,MACP,YAAY,QAAQ,cAAc;AAAA,MAClC,UAAU,QAAQ;AAAA,MAClB,QAAQ,QAAQ;AAAA,IAClB;AAAA,EACF,CAAC;AAED,SAAO,OAAO,GAAG;AACnB;AAEA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,OAAO,IAAI,CAAC;AAEtC,SAAS,mBACd,OACmD;AACnD,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,gBAAgB,IAAI,GAAG,GAAG;AAC5B,YAAM,IAAI,MAAM,4CAA4C,GAAG,GAAG;AAAA,IACpE;AAAA,EACF;AACA,SAAO,EAAE,GAAG,mBAAmB,GAAG,MAAM;AAC1C;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n ContextSchema,\n builtinEvaluators,\n ValidationError,\n DataError,\n resolve,\n} from \"@showwhat/core\";\nimport type {\n BuiltinCondition,\n ConditionEvaluators,\n Context,\n ContextValue,\n Definitions,\n DefinitionReader,\n Dependencies,\n Resolution,\n ResolutionError,\n ResolverOptions,\n} from \"@showwhat/core\";\n\nexport * from \"@showwhat/core\";\n\nexport type ShowWhatOptions = ResolverOptions & {\n data: DefinitionReader;\n};\n\nexport type Resolutions = Record<string, Resolution | ResolutionError>;\n\nasync function fetchDefinitions(data: DefinitionReader, keys?: string[]): Promise<Definitions> {\n if (!keys) {\n try {\n return await data.getAll();\n } catch (err) {\n throw new DataError(\"Failed to fetch definitions\", err);\n }\n }\n\n const definitions = {} as Record<string, Definitions[string] | null>;\n await Promise.all(\n keys.map(async (key) => {\n try {\n definitions[key] = await data.get(key);\n } catch (err) {\n throw new DataError(`Failed to fetch definition \"${key}\"`, err);\n }\n }),\n );\n return definitions as Definitions;\n}\n\nexport async function showwhat<\n T extends Record<string, ContextValue> = Record<string, ContextValue>,\n D extends Record<string, unknown> = Record<string, unknown>,\n>({\n keys,\n context,\n deps,\n options,\n}: {\n keys?: string[];\n context: Context<T>;\n deps?: Dependencies<D>;\n options: ShowWhatOptions;\n}): Promise<Resolutions> {\n const contextResult = ContextSchema.safeParse(context);\n if (!contextResult.success) {\n throw new ValidationError(\n contextResult.error.issues.map((i) => `[${i.path.join(\".\")}] ${i.message}`).join(\"; \"),\n \"context\",\n );\n }\n\n return resolve({\n definitions: await fetchDefinitions(options.data, keys),\n context: contextResult.data as Context<T>,\n deps,\n options: {\n ...options,\n evaluators: options.evaluators ?? builtinEvaluators,\n },\n });\n}\n\nconst COMPOSITE_TYPES = new Set([\"and\", \"or\"]);\n\nexport function registerEvaluators<T extends string>(\n extra: ConditionEvaluators<T>,\n): ConditionEvaluators<BuiltinCondition[\"type\"] | T> {\n for (const key of Object.keys(extra)) {\n if (COMPOSITE_TYPES.has(key)) {\n throw new Error(`Cannot register reserved condition type \"${key}\"`);\n }\n }\n return { ...builtinEvaluators, ...extra };\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAcP,cAAc;AAQd,eAAe,iBAAiB,MAAwB,MAAuC;AAC7F,MAAI,CAAC,MAAM;AACT,QAAI;AACF,aAAO,MAAM,KAAK,OAAO;AAAA,IAC3B,SAAS,KAAK;AACZ,YAAM,IAAI,UAAU,+BAA+B,GAAG;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,cAAc,CAAC;AACrB,QAAM,QAAQ;AAAA,IACZ,KAAK,IAAI,OAAO,QAAQ;AACtB,UAAI;AACF,oBAAY,GAAG,IAAI,MAAM,KAAK,IAAI,GAAG;AAAA,MACvC,SAAS,KAAK;AACZ,cAAM,IAAI,UAAU,+BAA+B,GAAG,KAAK,GAAG;AAAA,MAChE;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,eAAsB,SAGpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKyB;AACvB,QAAM,gBAAgB,cAAc,UAAU,OAAO;AACrD,MAAI,CAAC,cAAc,SAAS;AAC1B,UAAM,IAAI;AAAA,MACR,cAAc,MAAM,OAAO,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ;AAAA,IACb,aAAa,MAAM,iBAAiB,QAAQ,MAAM,IAAI;AAAA,IACtD,SAAS,cAAc;AAAA,IACvB;AAAA,IACA,SAAS;AAAA,MACP,GAAG;AAAA,MACH,YAAY,QAAQ,cAAc;AAAA,IACpC;AAAA,EACF,CAAC;AACH;AAEA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,OAAO,IAAI,CAAC;AAEtC,SAAS,mBACd,OACmD;AACnD,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,gBAAgB,IAAI,GAAG,GAAG;AAC5B,YAAM,IAAI,MAAM,4CAA4C,GAAG,GAAG;AAAA,IACpE;AAAA,EACF;AACA,SAAO,EAAE,GAAG,mBAAmB,GAAG,MAAM;AAC1C;","names":[]}
package/package.json CHANGED
@@ -1,13 +1,18 @@
1
1
  {
2
2
  "name": "showwhat",
3
- "version": "1.0.0",
4
- "description": "Feature flag resolution engine",
3
+ "version": "2.0.0",
4
+ "description": "A schema-based resolution engine for configuration and feature flags",
5
5
  "keywords": [
6
6
  "feature-flags",
7
7
  "feature-toggles",
8
8
  "feature-management",
9
+ "config-management",
9
10
  "flag-evaluation",
11
+ "resolution",
12
+ "engine",
10
13
  "targeting",
14
+ "schema",
15
+ "specification",
11
16
  "showwhat"
12
17
  ],
13
18
  "license": "MIT",
@@ -36,14 +41,14 @@
36
41
  "dist"
37
42
  ],
38
43
  "dependencies": {
39
- "@showwhat/core": "1.0.0"
44
+ "@showwhat/core": "2.0.0"
40
45
  },
41
46
  "devDependencies": {
42
- "@types/node": "^25.4.0",
43
- "@vitest/coverage-v8": "^4.0.0",
44
- "tsup": "^8.0.0",
45
- "typescript": "^5.4.0",
46
- "vitest": "^4.0.0"
47
+ "@types/node": "^25.5.0",
48
+ "@vitest/coverage-v8": "^4.1.2",
49
+ "tsup": "^8.5.1",
50
+ "typescript": "^5.9.3",
51
+ "vitest": "^4.1.2"
47
52
  },
48
53
  "scripts": {
49
54
  "build": "tsup",