@harshankur/viewcounter 3.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/.env.example ADDED
@@ -0,0 +1,115 @@
1
+ # ViewCounter configuration
2
+ #
3
+ # Copy to `.env` and fill in. Every value here can also come from dbInfo.json /
4
+ # allowed.json, which take precedence — see config/index.js for the resolution
5
+ # order (config file > environment variable > built-in default).
6
+ #
7
+ # Anything marked Required is checked at startup in production: the server
8
+ # refuses to boot rather than run on a guessable default.
9
+
10
+ # ---------------------------------------------------------------------------
11
+ # Required in production
12
+ # ---------------------------------------------------------------------------
13
+
14
+ # Database credentials. The server will not start in production while these are
15
+ # still root with an empty password.
16
+ DB_USER=viewcounter
17
+ DB_PASSWORD=
18
+
19
+ # Database to write into. Created automatically when DB_MODE=create.
20
+ DB_NAME=viewcounterdb
21
+
22
+ # Apps allowed to record views, comma-separated. This is an authorization
23
+ # boundary, not a convenience list: an appId absent from it is rejected, and it
24
+ # also determines which tables get created in `create` mode. The placeholder
25
+ # `example_app` is refused in production.
26
+ ALLOWED_APP_IDS=blog,portfolio
27
+
28
+ # Browser origins permitted to call the write endpoints, comma-separated.
29
+ # Required in production: without it, CORS blocks every browser caller. Use the
30
+ # exact scheme+host+port, no trailing slash.
31
+ CORS_ORIGINS=https://example.com,https://www.example.com
32
+
33
+ # ---------------------------------------------------------------------------
34
+ # Recommended
35
+ # ---------------------------------------------------------------------------
36
+
37
+ # Credentials for the analytics READ endpoints (/stats, /views, /trends, ...),
38
+ # comma-separated, sent by clients as the `x-api-key` header. Keys shorter than
39
+ # 32 characters are ignored. List several so one consumer's key can be revoked
40
+ # without rotating everyone else's. With none set, the read API returns 503 —
41
+ # it fails closed rather than serving your analytics to anyone who asks.
42
+ # Generate one with:
43
+ # node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
44
+ READ_API_KEYS=
45
+
46
+ # Credential for the ADMIN API (POST /apps, which provisions a new app and
47
+ # creates its table). A separate tier from READ_API_KEYS on purpose: leaking a
48
+ # tenant's read key must never confer the ability to create apps, and revoking
49
+ # one tier must not force rotating the other. Leave unset to disable
50
+ # provisioning over HTTP entirely.
51
+ ADMIN_API_KEYS=
52
+
53
+ # Number of reverse proxies in front of this service, or a comma-separated list
54
+ # of trusted proxy CIDRs. Leave unset if nothing proxies it.
55
+ #
56
+ # Do NOT set this to `true`. Trusting every hop means any caller can send their
57
+ # own X-Forwarded-For and be believed, which forges geolocation, inflates
58
+ # unique-visitor counts, and lets an attacker rotate the rate-limiter key to
59
+ # bypass it entirely. `true` and `*` are downgraded to a single hop with a
60
+ # warning. Your proxy must set X-Forwarded-For; X-Real-IP alone is not read.
61
+ #TRUST_PROXY=1
62
+
63
+ # Where the visitor-hash secret is persisted. Generated with a CSPRNG on first
64
+ # run at mode 0600. This secret is the only reason a stored visitor hash cannot
65
+ # be brute-forced back to the IP that produced it, so back it up with the same
66
+ # care as the database password — and note that replacing it makes existing
67
+ # hashes unlinkable from new ones (which is deliberate, not a bug).
68
+ #VISITOR_SECRET_PATH=/var/lib/viewcounter/.visitor-secret
69
+
70
+ # Supply the secret directly instead of persisting a file. Useful for
71
+ # containers with a read-only filesystem or an external secrets manager.
72
+ #VISITOR_SECRET=
73
+
74
+ # ---------------------------------------------------------------------------
75
+ # Optional
76
+ # ---------------------------------------------------------------------------
77
+
78
+ # `connect` uses an existing database; `create` creates the database and one
79
+ # table per allowed appId on startup. Default: connect.
80
+ DB_MODE=connect
81
+
82
+ DB_HOST=127.0.0.1
83
+ DB_PORT=3306
84
+
85
+ # Port the HTTP server listens on. Default: 3030.
86
+ PORT=3030
87
+
88
+ # Defaults to `production`. Set to `development` for local work. This does not
89
+ # change what is returned to callers — errors never include internal detail in
90
+ # any environment — but it does relax the startup checks above.
91
+ #NODE_ENV=production
92
+
93
+ # Operational log verbosity: debug | info | warn | error | silent.
94
+ # The audit trail for state-mutating actions is emitted regardless.
95
+ LOG_LEVEL=info
96
+
97
+ # Rate limiting, applied per client IP across all endpoints. This is the
98
+ # single-abuser backstop.
99
+ RATE_LIMIT_WINDOW_MS=60000
100
+ RATE_LIMIT_MAX=100
101
+
102
+ # Per-app ceiling on the write endpoints, within the same window. Stops one
103
+ # tenant consuming the budget every other tenant on the instance depends on.
104
+ # Keyed on appId only, so it cannot be bypassed by rotating IP addresses.
105
+ # Set 0 to disable (sensible for a single-tenant deployment).
106
+ APP_RATE_LIMIT_MAX=1000
107
+
108
+ # How long a visitor counts as "the same visitor" for deduplication, in hours.
109
+ # Also the rotation period for the visitor hash: after this window the same
110
+ # person hashes differently, so their visits cannot be linked across windows.
111
+ # Set 0 to disable deduplication (the hash still rotates hourly).
112
+ UNIQUE_VISITOR_WINDOW_HOURS=24
113
+
114
+ # Device size buckets accepted on /registerView, comma-separated.
115
+ #ALLOWED_DEVICE_SIZES=small,medium,large
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Harsh Ankur
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.