@jewel998/config 0.1.2 → 0.1.3

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.
Files changed (3) hide show
  1. package/LICENSE +84 -0
  2. package/README.md +234 -0
  3. package/package.json +21 -3
package/LICENSE ADDED
@@ -0,0 +1,84 @@
1
+ Elastic License 2.0 (ELv2)
2
+
3
+ ## Acceptance
4
+
5
+ By using the software, you agree to all of the terms and conditions below.
6
+
7
+ ## Copyright License
8
+
9
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
10
+ non-sublicensable, non-transferable license to use, copy, distribute, make
11
+ available, and prepare derivative works of the software, in each case subject
12
+ to the limitations below.
13
+
14
+ ## Limitations
15
+
16
+ You may not provide the software to third parties as a hosted or managed
17
+ service, where the service provides users with access to any substantial set
18
+ of the features or functionality of the software.
19
+
20
+ You may not move, change, disable, or circumvent the license key functionality
21
+ in the software, and you may not remove or obscure any functionality in the
22
+ software that is protected by the license key.
23
+
24
+ You may not alter, remove, or obscure any licensing, copyright, or other
25
+ notices of the licensor in the software.
26
+
27
+ ## Patents
28
+
29
+ The licensor grants you a license, under any patent claims the licensor can
30
+ license, or becomes able to license, to make, have made, use, sell, offer for
31
+ sale, import and have imported the software, in each case subject to the
32
+ limitations and conditions in this license. This license does not cover any
33
+ patent claims that you cause to be infringed by modifications or additions to
34
+ the software.
35
+
36
+ ## No Other Rights
37
+
38
+ These terms do not imply any licenses other than those expressly granted in
39
+ these terms.
40
+
41
+ ## Termination
42
+
43
+ If you use the software in violation of these terms, such use is not licensed,
44
+ and your licenses will automatically terminate. If the licensor provides you
45
+ with a notice of your violation, and you cease all violation of this license no
46
+ later than 30 days after you receive that notice, your licenses will be
47
+ reinstated retroactively. However, if you violate these terms after such
48
+ reinstatement, any additional violation of these terms will cause your licenses
49
+ to terminate automatically and permanently.
50
+
51
+ ## No Liability
52
+
53
+ As far as the law allows, the software comes as is, without any warranty or
54
+ condition, and the licensor will not be liable to you for any damages arising
55
+ out of these terms or the use or nature of the software, under any kind of
56
+ legal claim.
57
+
58
+ ## Definitions
59
+
60
+ The **licensor** is the entity offering these terms, and the **software** is
61
+ the software the licensor makes available under these terms, including any
62
+ portion of it.
63
+
64
+ **You** refers to the individual or entity agreeing to these terms.
65
+
66
+ **Your company** is any legal entity, sole proprietorship, or other kind of
67
+ organization that you work for, plus all organizations that have control over,
68
+ are under the control of, or are under common control with that organization.
69
+
70
+ **Control** means ownership of substantially all the assets of an entity, or
71
+ the power to direct its management and policies by vote, contract, or
72
+ otherwise. Control can be direct or indirect.
73
+
74
+ **Your licenses** are all the licenses granted to you for the software under
75
+ these terms.
76
+
77
+ **Use** means anything you do with the software requiring one of your licenses.
78
+
79
+ **Trademark** this license does not grant any rights in the trademarks, service
80
+ marks, brand names, or logos of the licensor.
81
+
82
+ ---
83
+
84
+ Copyright (c) 2024-present Jyotirmoy Barman. All Rights Reserved.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # @jewel998/config
2
+
3
+ A free, self-hostable feature flag and remote configuration platform. Deploy to your own Firebase project. Replace LaunchDarkly at $0/month.
4
+
5
+ ## Features
6
+
7
+ - **Feature flags** — Boolean, string, number, JSON, array value types
8
+ - **Targeting rules** — Serve different values based on user attributes (plan, country, etc.)
9
+ - **Segments** — Reusable audience groups with one-click targeting
10
+ - **Percentage rollouts** — Gradually roll out features with deterministic bucketing
11
+ - **Prerequisites** — Flag dependencies with operator support (equals, greater_than, etc.)
12
+ - **Scheduling** — Schedule config changes for a future date/time
13
+ - **Environments** — Separate dev/staging/production configs
14
+ - **Audit log** — Track every change with actor, timestamp, and diff viewer
15
+ - **Webhooks** — Notify Slack, Discord, Google Chat, MS Teams, or custom endpoints
16
+ - **RBAC** — Viewer, Editor, Admin roles per project
17
+ - **Server-side evaluation** — Client keys never expose targeting rules or segments
18
+ - **SDK** — Optimistic defaults, auto-context detection, instant reads
19
+ - **Self-hosted** — Runs entirely on Firebase free tier ($0/month)
20
+ - **7 languages** — English, Spanish, French, Arabic, Chinese, Hindi, Japanese
21
+
22
+ ## Self-Hosting
23
+
24
+ ```bash
25
+ # 1. Clone
26
+ git clone https://github.com/jewel998/config && cd config
27
+
28
+ # 2. Connect your Firebase project
29
+ firebase use --add your-project-id
30
+
31
+ # 3. Install and deploy
32
+ pnpm install && firebase deploy
33
+ ```
34
+
35
+ That's it. Portal, API, and hosting — all on your Firebase project.
36
+
37
+ ## SDK Quick Start
38
+
39
+ ```bash
40
+ npm install @jewel998/config
41
+ ```
42
+
43
+ ```typescript
44
+ import { initConfig, autoContext } from "@jewel998/config";
45
+
46
+ const flags = initConfig({
47
+ clientId: "cid_xxx", // From your Portal → API Keys
48
+ baseUrl: "https://your-project.web.app/api", // Your Firebase URL
49
+ defaults: {
50
+ "feature.dark_mode": false,
51
+ "app.upload_limit": 50,
52
+ },
53
+ context: autoContext({ userId: "user_123", plan: "pro" }),
54
+ });
55
+
56
+ // Instant — returns default value, no loading state
57
+ flags.get("feature.dark_mode"); // → false
58
+
59
+ // After API responds, returns resolved value
60
+ flags.on("updated", () => {
61
+ flags.get("feature.dark_mode"); // → true (matched targeting rule)
62
+ });
63
+ ```
64
+
65
+ ### API Key Types
66
+
67
+ | Prefix | Type | Behavior |
68
+ | ------ | ------ | ------------------------------------------------------------------------------------------------------------------- |
69
+ | `cid_` | Client | For frontend. API evaluates targeting server-side, returns only values. Targeting rules and segments never exposed. |
70
+ | `svr_` | Server | For backend. API returns full flag data + segments for local evaluation via plugins. |
71
+
72
+ The API enforces the mode based on key prefix — cannot be overridden.
73
+
74
+ ### Server Key (Backend)
75
+
76
+ ```typescript
77
+ import { createConfig } from "@jewel998/config";
78
+ import { targetingPlugin } from "@jewel998/config/targeting";
79
+ import { rolloutPlugin } from "@jewel998/config/rollout";
80
+
81
+ const config = createConfig({
82
+ clientId: "svr_xxx",
83
+ baseUrl: "https://your-project.web.app/api",
84
+ plugins: [targetingPlugin(), rolloutPlugin()],
85
+ context: { userId: "user_123", attributes: { plan: "pro", country: "US" } },
86
+ });
87
+
88
+ config.getFlag("feature.checkout_v2"); // Evaluated locally — no round-trip
89
+ ```
90
+
91
+ ## Architecture
92
+
93
+ ```
94
+ ┌─────────────────────────────────────────────────────┐
95
+ │ Your App │
96
+ │ │
97
+ │ import { initConfig } from "@jewel998/config" │
98
+ │ const flags = initConfig({ clientId, baseUrl }) │
99
+ │ flags.get("feature.dark_mode") → true │
100
+ └──────────────────────┬──────────────────────────────┘
101
+ │ POST /api/getConfig
102
+ ▼
103
+ ┌──────────────────────────────────────────────────────┐
104
+ │ Your Firebase Hosting (CDN cached) │
105
+ └──────────────────────┬───────────────────────────────┘
106
+ │ cache miss
107
+ ▼
108
+ ┌──────────────────────────────────────────────────────┐
109
+ │ Your Cloud Function: getConfig │
110
+ │ - Validates clientId (cid_ or svr_) │
111
+ │ - cid_: evaluates targeting server-side │
112
+ │ - svr_: returns full flag data for local eval │
113
+ └──────────────────────┬───────────────────────────────┘
114
+ │
115
+ ▼
116
+ ┌──────────────────────────────────────────────────────┐
117
+ │ Your Firestore (configs, segments, projects) │
118
+ └──────────────────────────────────────────────────────┘
119
+ ▲
120
+ │
121
+ ┌──────────────────────┴───────────────────────────────┐
122
+ │ Your Portal (React SPA on Firebase Hosting) │
123
+ │ - Create/edit feature flags and segments │
124
+ │ - Set targeting rules, rollouts, schedules │
125
+ │ - Manage team, environments, API keys │
126
+ │ - View audit log with diff viewer │
127
+ │ - Configure webhook notifications │
128
+ └──────────────────────────────────────────────────────┘
129
+ ```
130
+
131
+ ## API Reference
132
+
133
+ ### POST /api/getConfig
134
+
135
+ The SDK calls this endpoint. Mode is determined by the API key prefix.
136
+
137
+ **Request:**
138
+
139
+ ```json
140
+ {
141
+ "data": {
142
+ "clientId": "cid_xxx",
143
+ "context": {
144
+ "userId": "user_123",
145
+ "attributes": { "plan": "pro", "country": "US" }
146
+ }
147
+ }
148
+ }
149
+ ```
150
+
151
+ **Response (cid\_ key) — resolved values only:**
152
+
153
+ ```json
154
+ {
155
+ "data": { "feature.dark_mode": true, "app.upload_limit": 200 },
156
+ "version": "3",
157
+ "timestamp": "2025-01-15T09:30:00.000Z"
158
+ }
159
+ ```
160
+
161
+ **Response (svr\_ key) — full flag data + segments:**
162
+
163
+ ```json
164
+ {
165
+ "data": {
166
+ "feature.dark_mode": {
167
+ "key": "feature.dark_mode",
168
+ "value": false,
169
+ "targetingRules": [...]
170
+ }
171
+ },
172
+ "segments": { "seg_beta": { "id": "...", "conditions": [...] } },
173
+ "version": "3",
174
+ "timestamp": "2025-01-15T09:30:00.000Z"
175
+ }
176
+ ```
177
+
178
+ **Errors:** `401` Invalid key · `403` Domain not allowed · `413` Context too large
179
+
180
+ ## Monorepo Structure
181
+
182
+ ```
183
+ apps/
184
+ portal/ — Admin portal (React + Vite + TanStack Router)
185
+ landing/ — Marketing site (Astro + React)
186
+ docs/ — Documentation (VitePress)
187
+ packages/
188
+ config/ — SDK (@jewel998/config)
189
+ tour/ — Tour framework (@jewel998/tour)
190
+ functions/ — Firebase Cloud Functions (API + webhooks)
191
+ ```
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ pnpm install # Install deps
197
+ pnpm --filter @jewel998/config-portal run dev # Portal dev server
198
+ pnpm --filter @jewel998/config-landing run dev # Landing page dev
199
+ pnpm --filter @jewel998/config run test # SDK tests (210 passing)
200
+ firebase deploy # Deploy everything
201
+ ```
202
+
203
+ ## Upgrades
204
+
205
+ When new versions are released, pull the latest and redeploy:
206
+
207
+ ```bash
208
+ git pull origin main
209
+ pnpm install
210
+ firebase deploy
211
+ ```
212
+
213
+ Migration guides are provided for breaking changes. Your data stays in your Firestore.
214
+
215
+ ## Cost
216
+
217
+ The SDK polls a lightweight version endpoint (100 bytes) every 5 minutes. CDN absorbs 99%+ of these requests. Full config fetches only happen on init or version change.
218
+
219
+ | Scale | Monthly Cost | Notes |
220
+ | -------------------- | ------------ | --------------------------------------------- |
221
+ | 1–1,000 users | **$0** | Well within Firebase Spark (free) tier |
222
+ | 1,000–50,000 users | **$0** | CDN handles most version polls at edge |
223
+ | 50,000–100,000 users | **$0–5** | May slightly exceed free function invocations |
224
+ | 100,000+ users | **$5–15** | Blaze plan with minimal overage |
225
+
226
+ Firebase free tier: 2M function invocations/month, 50K Firestore reads/day, 10GB bandwidth.
227
+
228
+ ## License
229
+
230
+ [Elastic License 2.0](./LICENSE) — Use, modify, and self-host freely. Cannot be provided as a managed service to third parties.
231
+
232
+ ## Contributing
233
+
234
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions, commit conventions, and PR guidelines.
package/package.json CHANGED
@@ -1,16 +1,33 @@
1
1
  {
2
2
  "name": "@jewel998/config",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "Free, self-hosted feature flags and remote configuration SDK",
8
+ "author": "Jyotirmoy Barman",
9
+ "homepage": "https://github.com/jewel998/config#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/jewel998/config/issues"
12
+ },
13
+ "keywords": [
14
+ "feature-flags",
15
+ "remote-config",
16
+ "feature-toggles",
17
+ "self-hosted",
18
+ "firebase",
19
+ "sdk",
20
+ "configuration",
21
+ "targeting",
22
+ "rollout",
23
+ "a-b-testing"
24
+ ],
8
25
  "repository": {
9
26
  "type": "git",
10
27
  "url": "git+https://github.com/jewel998/config.git",
11
28
  "directory": "packages/config"
12
29
  },
13
- "license": "SEE LICENSE IN LICENSE",
30
+ "license": "Elastic-2.0",
14
31
  "main": "./dist/index.js",
15
32
  "types": "./dist/index.d.ts",
16
33
  "exports": {
@@ -53,7 +70,8 @@
53
70
  },
54
71
  "files": [
55
72
  "dist",
56
- "README.md"
73
+ "README.md",
74
+ "LICENSE"
57
75
  ],
58
76
  "engines": {
59
77
  "node": ">=22.0.0"