Skip to content

Commit 16363f1

Browse files
committed
Added docs folder.
1 parent c2f3a00 commit 16363f1

File tree

5 files changed

+649
-1
lines changed

5 files changed

+649
-1
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ dist
88
compiled
99
.awcache
1010
.rpt2_cache
11-
docs

docs/README.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
@zimmed/const / [Exports](modules.md)
2+
3+
# @zimmed/const
4+
5+
A simple library for managing Constants in project features.
6+
7+
> [Documentation](docs/README.md)
8+
9+
![Jest Branch Coverage](coverage/badge-branches.svg)
10+
![Jest Function Coverage](coverage/badge-functions.svg)
11+
![Jest Line Coverage](coverage/badge-lines.svg)
12+
![Jest Statement Coverage](coverage/badge-statements.svg)
13+
14+
## Installation
15+
16+
First, edit existing or create new .npmrc file in your project root, and add:
17+
18+
`@zimmed:registry=https://npm.pkg.github.com`
19+
20+
Then you can use:
21+
22+
`$ npm i --save @zimmed/const`
23+
24+
## Usage
25+
26+
### Problem
27+
28+
Defining lots of groups of constants without any kind of forced structure for value and label.
29+
30+
Typically, you might see something like this:
31+
32+
```typescript
33+
// food/constants/index.js
34+
export * as FRUIT from './fruit';
35+
export * as VEGGIES from './veggies';
36+
37+
// food/constants/fruit.js
38+
export const APPLE = 'apple';
39+
export const LEMON = 'lemon';
40+
export const LIME = 'lime';
41+
42+
export const INFO = {
43+
[APPLE]: { value: APPLE, label: 'Apple' },
44+
[LEMON]: { value: LEMON, label: 'Lemon', sour: true },
45+
[LIME]: { value: LIME, label: 'Lime', sour: true },
46+
};
47+
48+
// food/other.js
49+
import { FRUIT } from './constants';
50+
51+
export function isFoodSour(food) {
52+
return !!FRUIT.INFO[food.fruit]?.sour;
53+
}
54+
55+
export function getAppleName() {
56+
return FRUIT.INFO[FRUIT.APPLE].label;
57+
}
58+
```
59+
60+
### Solution
61+
62+
With this library, rather than having a weakly-enforced costant structure, you can enforce a label/value structure (with optional extended properties) where the keys and info do not have to be defined separately, as the const is the full info object, but reduces to the key if cast to string or json-string.
63+
64+
```typescript
65+
// food/constants/index.js
66+
export { default as FRUIT } from './fruit';
67+
export { default as VEGGIES } from './veggies';
68+
69+
// food/constants/fruit.js
70+
import Const from '@zimmed/const';
71+
72+
export default Const.createMap(
73+
{
74+
APPLE: { singular: 'Apple', plural: 'Apples' },
75+
LEMON: { singular: 'Lemon', plural: 'Lemons', label: 'Citron', sour: true },
76+
LIME: { singular: 'Lime', plural: 'Limes', sour: true },
77+
},
78+
'singular'
79+
); // -> second arg is a property name to use as the default label (if none specified)
80+
81+
// food/other.js
82+
import { FRUIT } from './constants';
83+
84+
export function isFoodSour(food) {
85+
return !!FRUIT[food.fruit]?.sour;
86+
}
87+
88+
export function getAppleName() {
89+
return FRUIT.APPLE.label;
90+
}
91+
```
92+
93+
### A Common Example
94+
95+
```typescript
96+
import Const from '@zimmed/const';
97+
98+
export default FRUIT = Const.createMap({
99+
Apple: { color: 'red' },
100+
Lemon: { color: 'yellow', label: 'Citron', sour: true },
101+
Lime: { color: 'green', sour: true },
102+
});
103+
```
104+
105+
```typescript
106+
import * as React from 'react';
107+
import FRUIT from './fruit';
108+
109+
export default function MyPie({ onUpdateFood }) {
110+
const [fruit, setFruit] = React.useState(FRUIT.APPLE);
111+
const { current: selectFruit } = React.useRef((e) => setFruit(FRUIT[e.target.value]));
112+
const onConfirm = React.useCallback(() => {
113+
const body = JSON.stringify({ name: `${fruit.label} Pie`, ingredients: [fruit] });
114+
115+
// body -> {"name":"Apple Pie","ingredients":["APPLE"]}
116+
onUpdateFood(body).then(() => alert('Updated!'));
117+
});
118+
119+
return (
120+
<div>
121+
<h1>My {fruit.label} Pie</h1>
122+
<h2>It will be {fruit.sour ? 'sour' : 'sweet'}!</h2>
123+
<label for="fruit-selector">Select a fruit for the pie!</label>
124+
<select id="fruit-selector" value={fruit.value} onChange={selectFruit}>
125+
{Array.from(FRUIT).map(({ value, label }) => (
126+
<option key={value} value={value}>
127+
{label}
128+
</option>
129+
))}
130+
</select>
131+
<button onClick={onConfirm}>Update Food</button>
132+
</div>
133+
);
134+
}
135+
```
136+
137+
### As A Simple Enum
138+
139+
```typescript
140+
const FRUIT = Const.list('Apple', 'Lemon', 'Lime', 'Mango', 'Cherry');
141+
142+
console.log(FRUIT.Lemon); // -> Lemon
143+
console.log(FRUIT.Mango.label); // -> Mango
144+
```
145+
146+
### Using Strictly-Typed Extended Data
147+
148+
If you want to enforce that all extended const data meets a particular structure, you can use the aliases `createTypedMap`, `createStrictMap`, etc.
149+
150+
```typescript
151+
const FRUIT = Const.createTypedMap<{ plural?: string; singular: string }>()(
152+
{
153+
APPLE: { singular: 'apple', plural: 'apples' },
154+
LEMON: { singular: 'lemon' },
155+
LIME: { plural: 'limes' }, // <- Typescript complains that `singular` prop is missing
156+
},
157+
'singular'
158+
);
159+
```
160+
161+
### Iterating
162+
163+
```typescript
164+
const fruits = Array.from(FRUIT);
165+
166+
for (const fruit of FRUIT) {
167+
// iterate over each constant
168+
}
169+
```

0 commit comments

Comments
 (0)