Skip to content

Commit

Permalink
Filters (#3)
Browse files Browse the repository at this point in the history
* WIP enums

* WIP types

* working filter

* init tests

* tests

* readme and cleanup

* bundle

* desc
  • Loading branch information
hasnainroopawalla committed Apr 13, 2024
1 parent e7ff8fd commit 83f957a
Show file tree
Hide file tree
Showing 19 changed files with 679 additions and 2,523 deletions.
6 changes: 2 additions & 4 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "react-hooks"],
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
Expand Down Expand Up @@ -35,8 +35,6 @@
"varsIgnorePattern": "^_",
"ignoreRestSiblings": true
}
],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
]
}
}
110 changes: 108 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,108 @@
# configwise
config provider ⚙️
# Configwise

Crafting Dynamic Project Configs based on your Browser’s Whims 🌟

`configwise` is a lightweight, strongly-typed package to build and serve project configurations based on the browser environment, platform, os, engine, etc.

## 🏁 Getting started

```
$ npm install configwise
// OR
$ yarn add configwise
```

## 💻 Installation

```
$ git clone https://github.com/hasnainroopawalla/configwise.git
$ cd configwise
$ yarn install
```

## 💡 Usage

`configwise.createConfig` should be executed once on app init. The current browser/OS environment is detected and parsed by [bowser](https://www.npmjs.com/package/bowser) using the `window.navigator.userAgent`.

`configwise` builds and serves the appropriate config property values based on the user-created project configuration with filters such as `Browser`, `Platform`, `OS` and `Engine`.

> These enums are inferred from the bowser package.
Example: Create a configuration for your project with 2 properties - `showButton` and `themeColors` with the appropriate values based on the environment:

```javascript
// config.ts

import { createConfig, Browser, OS, Platform, Engine } from "configwise";

export const config = createConfig({
showButton: {
// default fallback base value if no filters are satisfied
value: true,
filters: [
{
// a filter to set this property as false for Edge and Firefox on MacOS
browser: [Browser.Edge, Browser.Firefox],
os: [OS.MacOS],
value: false,
},
{
// a filter to set this property as true for Chrome on Mobile
browser: [Browser.Chrome],
platform: [Platform.Mobile],
value: true,
},
],
},

themeColors: {
value: {
light: "#ffffff",
dark: "#000000",
},
filters: [
{
browser: [Browser.InternetExplorer],
engine: [Engine.EdgeHTML]
value: {
light: "#dbdbdb",
dark: "#141414",
},
},
],
},
});
```

Import the created `config` in any other file with full type-safety:

```javascript
import * as React from "react";
import config from "./config";

const MyComponent: React.FC = () => {
// typeof config is inferred and strictly-typed as:
//
// typeof config = {
// showButton: boolean;
// themeColors: {
// light: string;
// dark: string;
// }
// }

const shouldShowButton = config.showButton;

return (
<>
<span>Some text</span>
{shouldShowButton && <button onClick={() => {}}>Submit</button>}
</>
);
};
```

## ✏️ Contributing

- Post any issues and suggestions on the GitHub [issues](https://github.com/hasnainroopawalla/configwise/issues) page.
- To contribute, fork the project and then create a pull request back to `master`.
19 changes: 5 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"name": "configwise",
"version": "0.1.1",
"description": "",
"description": "Crafting Dynamic Project Configs based on your Browser's Whims ⚙️",
"repository": "https://github.com/hasnainroopawalla/configwise",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"start": "parcel src/index.html",
"build": "tsc",
"prepare": "yarn build",
"publish:dry-run": "npm publish --dry-run",
Expand All @@ -24,30 +23,22 @@
"typescript",
"react",
"config",
"settings"
"settings",
"bowser"
],
"author": "Hasnain Roopawalla",
"license": "MIT",
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/react": "^18.2.74",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"bowser": "^2.11.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"process": "^0.11.10",
"react": "^18.2.0",
"ts-jest": "^29.1.2",
"tslib": "^2.6.2",
"typescript": "^5.4.2"
},
"dependencies": {
"@types/react-dom": "^18.2.23",
"bowser": "^2.11.0",
"parcel": "^2.12.0",
"react-dom": "^18.2.0"
}
}
}
34 changes: 0 additions & 34 deletions src/config-context.interface.ts

This file was deleted.

28 changes: 0 additions & 28 deletions src/config-context.tsx

This file was deleted.

31 changes: 31 additions & 0 deletions src/config.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Browser, Engine, OS, Platform } from "./enums";

type OneOf<T> = {
[K in keyof T]-?: Pick<T, K> & Partial<T>;
}[keyof T];

export type IFilterValue<TProp> = OneOf<{
browser: Browser[];
os: OS[];
platform: Platform[];
engine: Engine[];
}> & { value: TProp };

export type IProperty<TProp> = {
value: TProp;
filters?: IFilterValue<TProp>[];
};

/**
* A strongly typed `userConfig` object required to create the `IConfig` object.
*/
export type IUserConfig<TConfig> = {
[K in keyof TConfig]: IProperty<TConfig[K]>;
};

/**
* A type-safe object of the config parameters and corresponding values.
*/
export type IConfig<TConfig> = {
[K in keyof TConfig]: TConfig[K];
};
19 changes: 0 additions & 19 deletions src/config.ts

This file was deleted.

24 changes: 24 additions & 0 deletions src/create-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { PropertyParser } from "./property-parser";
import type { IConfig, IUserConfig } from "./config.interface";
import { getEnvironment } from "./environment";

/**
* Creates a configwise project configuration.
*
* @param userConfig - The project configuration with filters, properties and values.
* @returns The filtered property values based on the browser environment.
*/
export function createConfig<TUserConfig>(
userConfig: IUserConfig<TUserConfig>
) {
const environment = getEnvironment();
const propParser = new PropertyParser(environment);

const configValues: IConfig<TUserConfig> = {} as IConfig<TUserConfig>;

for (const propertyName in userConfig) {
configValues[propertyName] = propParser.getValue(userConfig[propertyName]);
}

return configValues;
}
Loading

0 comments on commit 83f957a

Please sign in to comment.