@valbuild/shared 0.150.16 → 0.150.17

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @valbuild/shared
2
2
 
3
+ ## 0.150.17
4
+
5
+ ### Patch Changes
6
+
7
+ - [#992](https://github.com/valbuild/val/pull/992) [`ea3bf9b`](https://github.com/valbuild/val/commit/ea3bf9bbacd22bbb5485fd798d6b3a2d5916be81) Thanks [@freekh](https://github.com/freekh)! - Content analytics now counts on self-hosted sites (Custom hosting), not only on sites Val hosts.
8
+
9
+ A self-hosted app's own Val server now hands each analytics beacon on to Val's ingest, which counts it. To turn it on:
10
+
11
+ - Run the app with Val's content service: `VAL_API_KEY`, `VAL_SECRET` and `VAL_PROJECT` set. Most deployed apps already do.
12
+ - Set `VAL_ANALYTICS=true`. In TanStack Start, read it in your layout's loader (`{ enabled: process.env.VAL_ANALYTICS === "true" }`) and pass the result to `<ValProvider analytics>`. A self-hosted site has no platform to pass it for you.
13
+ - Switch analytics on for the project in Val's admin. While it is off there, the script on your pages is told so and stops sending.
14
+
15
+ The server forwards only same-origin beacons from a browser. It passes on the visitor's User-Agent and, where your host provides one (Vercel, Cloudflare or CloudFront), their country. It never passes on their IP address. If the api key is not accepted, the server logs one warning naming `VAL_API_KEY` and `VAL_PROJECT`. Local development (fs mode) works as before and counts nothing.
16
+
17
+ `VAL_ANALYTICS_INGEST_URL` overrides where beacons are sent. You will normally not need it.
18
+
3
19
  ## 0.150.16
4
20
 
5
21
  ### Patch Changes
@@ -176,6 +176,13 @@ export declare const Api: {
176
176
  POST: {
177
177
  req: {
178
178
  body: z.ZodUnknown;
179
+ headers: {
180
+ "sec-fetch-site": z.ZodOptional<z.ZodString>;
181
+ "user-agent": z.ZodOptional<z.ZodString>;
182
+ "x-vercel-ip-country": z.ZodOptional<z.ZodString>;
183
+ "cf-ipcountry": z.ZodOptional<z.ZodString>;
184
+ "cloudfront-viewer-country": z.ZodOptional<z.ZodString>;
185
+ };
179
186
  };
180
187
  res: z.ZodUnion<readonly [z.ZodObject<{
181
188
  status: z.ZodLiteral<200>;
@@ -187,6 +194,11 @@ export declare const Api: {
187
194
  json: z.ZodObject<{
188
195
  message: z.ZodString;
189
196
  }, z.core.$strip>;
197
+ }, z.core.$strip>, z.ZodObject<{
198
+ status: z.ZodLiteral<410>;
199
+ json: z.ZodObject<{
200
+ message: z.ZodString;
201
+ }, z.core.$strip>;
190
202
  }, z.core.$strip>]>;
191
203
  };
192
204
  };
@@ -1754,11 +1754,22 @@ var Api = {
1754
1754
  // Parsed by the handler rather than here, so a beacon of a version this
1755
1755
  // server does not know is ignored instead of refused.
1756
1756
  req: {
1757
- body: zod.z.unknown()
1757
+ body: zod.z.unknown(),
1758
+ // What a server that forwards beacons to Val's ingest has to check
1759
+ // and pass on itself: a forward loses the browser's own headers. The
1760
+ // visitor's IP is deliberately not one of them.
1761
+ headers: {
1762
+ "sec-fetch-site": zod.z.string().optional(),
1763
+ "user-agent": zod.z.string().optional(),
1764
+ "x-vercel-ip-country": zod.z.string().optional(),
1765
+ "cf-ipcountry": zod.z.string().optional(),
1766
+ "cloudfront-viewer-country": zod.z.string().optional()
1767
+ }
1758
1768
  },
1759
1769
  res: zod.z.union([
1760
- // `counted` is false wherever nothing stores the counts -- every
1761
- // server but the hosted platform's, for now.
1770
+ // `counted` is true only where the beacon was handed to Val's ingest
1771
+ // and it counted it: the hosted platform, or a self-hosted server in
1772
+ // http mode. False everywhere else, local dev included.
1762
1773
  zod.z.object({
1763
1774
  status: zod.z.literal(200),
1764
1775
  json: zod.z.object({
@@ -1767,6 +1778,12 @@ var Api = {
1767
1778
  }), zod.z.object({
1768
1779
  status: zod.z.literal(400),
1769
1780
  json: GenericError
1781
+ }),
1782
+ // Analytics is switched off for this project in Val's admin. The
1783
+ // browser script stops sending when it sees this.
1784
+ zod.z.object({
1785
+ status: zod.z.literal(410),
1786
+ json: GenericError
1770
1787
  })])
1771
1788
  }
1772
1789
  },
@@ -1754,11 +1754,22 @@ var Api = {
1754
1754
  // Parsed by the handler rather than here, so a beacon of a version this
1755
1755
  // server does not know is ignored instead of refused.
1756
1756
  req: {
1757
- body: zod.z.unknown()
1757
+ body: zod.z.unknown(),
1758
+ // What a server that forwards beacons to Val's ingest has to check
1759
+ // and pass on itself: a forward loses the browser's own headers. The
1760
+ // visitor's IP is deliberately not one of them.
1761
+ headers: {
1762
+ "sec-fetch-site": zod.z.string().optional(),
1763
+ "user-agent": zod.z.string().optional(),
1764
+ "x-vercel-ip-country": zod.z.string().optional(),
1765
+ "cf-ipcountry": zod.z.string().optional(),
1766
+ "cloudfront-viewer-country": zod.z.string().optional()
1767
+ }
1758
1768
  },
1759
1769
  res: zod.z.union([
1760
- // `counted` is false wherever nothing stores the counts -- every
1761
- // server but the hosted platform's, for now.
1770
+ // `counted` is true only where the beacon was handed to Val's ingest
1771
+ // and it counted it: the hosted platform, or a self-hosted server in
1772
+ // http mode. False everywhere else, local dev included.
1762
1773
  zod.z.object({
1763
1774
  status: zod.z.literal(200),
1764
1775
  json: zod.z.object({
@@ -1767,6 +1778,12 @@ var Api = {
1767
1778
  }), zod.z.object({
1768
1779
  status: zod.z.literal(400),
1769
1780
  json: GenericError
1781
+ }),
1782
+ // Analytics is switched off for this project in Val's admin. The
1783
+ // browser script stops sending when it sees this.
1784
+ zod.z.object({
1785
+ status: zod.z.literal(410),
1786
+ json: GenericError
1770
1787
  })])
1771
1788
  }
1772
1789
  },
@@ -1747,11 +1747,22 @@ var Api = {
1747
1747
  // Parsed by the handler rather than here, so a beacon of a version this
1748
1748
  // server does not know is ignored instead of refused.
1749
1749
  req: {
1750
- body: z.unknown()
1750
+ body: z.unknown(),
1751
+ // What a server that forwards beacons to Val's ingest has to check
1752
+ // and pass on itself: a forward loses the browser's own headers. The
1753
+ // visitor's IP is deliberately not one of them.
1754
+ headers: {
1755
+ "sec-fetch-site": z.string().optional(),
1756
+ "user-agent": z.string().optional(),
1757
+ "x-vercel-ip-country": z.string().optional(),
1758
+ "cf-ipcountry": z.string().optional(),
1759
+ "cloudfront-viewer-country": z.string().optional()
1760
+ }
1751
1761
  },
1752
1762
  res: z.union([
1753
- // `counted` is false wherever nothing stores the counts -- every
1754
- // server but the hosted platform's, for now.
1763
+ // `counted` is true only where the beacon was handed to Val's ingest
1764
+ // and it counted it: the hosted platform, or a self-hosted server in
1765
+ // http mode. False everywhere else, local dev included.
1755
1766
  z.object({
1756
1767
  status: z.literal(200),
1757
1768
  json: z.object({
@@ -1760,6 +1771,12 @@ var Api = {
1760
1771
  }), z.object({
1761
1772
  status: z.literal(400),
1762
1773
  json: GenericError
1774
+ }),
1775
+ // Analytics is switched off for this project in Val's admin. The
1776
+ // browser script stops sending when it sees this.
1777
+ z.object({
1778
+ status: z.literal(410),
1779
+ json: GenericError
1763
1780
  })])
1764
1781
  }
1765
1782
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/shared",
3
- "version": "0.150.16",
3
+ "version": "0.150.17",
4
4
  "private": false,
5
5
  "description": "Val shared types and utilities",
6
6
  "repository": {