@stacksjs/defaults 0.74.67 → 0.74.69

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.
@@ -122,6 +122,13 @@ interface GoogleAnalyticsConfig {
122
122
  debug?: boolean // debug_mode -> DebugView
123
123
  }
124
124
 
125
+ interface AnalyticsHqConfig {
126
+ siteId: string // the data-site id AnalyticsHQ minted
127
+ scriptUrl?: string // self-hosted instance or verified custom domain
128
+ respectDnt?: boolean // false counts DNT/GPC visitors (skipped by default)
129
+ vitals?: boolean // false stops Core Web Vitals beacons
130
+ }
131
+
125
132
  interface SelfHostedConfig {
126
133
  siteId: string // unique site identifier
127
134
  apiEndpoint: string // analytics API URL
@@ -135,8 +142,9 @@ interface SelfHostedConfig {
135
142
 
136
143
  ```typescript
137
144
  {
138
- driver: 'fathom', // 'fathom' | 'plausible' | 'google-analytics' | 'self-hosted'
145
+ driver: 'fathom', // 'fathom' | 'plausible' | 'google-analytics' | 'self-hosted' | 'analyticshq'
139
146
  drivers: {
147
+ analyticshq: { siteId: '' },
140
148
  googleAnalytics: { trackingId: '' },
141
149
  fathom: { siteId: '' },
142
150
  plausible: { domain: '' },
@@ -167,3 +175,4 @@ Analytics dashboard at `/dashboard/analytics` displays:
167
175
  - Fathom is a paid service - self-hosted is free but requires infrastructure
168
176
  - `trackOutboundLinks` adds click handlers to external `<a>` tags
169
177
  - `capturePageviews` is server-side and independent of `driver`
178
+ - AnalyticsHQ custom events need no script: `data-analyticshq-event="Ticket click"` on any element, with other `data-analyticshq-*` attributes as properties
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.74.67",
5
+ "version": "0.74.69",
6
6
  "description": "A modern Stacks development environment.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.74.67",
5
+ "version": "0.74.69",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@iconify-json/f7": "^1.2.2",
57
57
  "@iconify-json/hugeicons": "^1.2.27",
58
- "@stacksjs/mobile": "^0.74.67",
58
+ "@stacksjs/mobile": "^0.74.69",
59
59
  "@stacksjs/sanitizer": "^0.2.113",
60
60
  "ts-qr-codes": "^0.1.8"
61
61
  }
package/routes/email.ts CHANGED
@@ -53,8 +53,8 @@ function emailConfig(): EmailConfigShape {
53
53
  // Unsubscribe — signed-link opt-out (stacksjs/stacks#1880)
54
54
  // ============================================================================
55
55
 
56
- route.get('/_stacks/email/unsubscribe/{token}', async (req) => {
57
- const params = (req as unknown as { params?: { token?: string } }).params
56
+ async function unsubscribe(req: unknown): Promise<Response> {
57
+ const params = (req as { params?: { token?: string } }).params
58
58
  const token = params?.token ?? ''
59
59
  const result = verifyUnsubscribeToken(token)
60
60
  if (!result.valid || !result.email) {
@@ -68,7 +68,17 @@ route.get('/_stacks/email/unsubscribe/{token}', async (req) => {
68
68
  `You've been unsubscribed. We won't email ${result.email} again.`,
69
69
  { status: 200, headers: { 'Content-Type': 'text/plain; charset=utf-8' } },
70
70
  )
71
- }).skipCsrf()
71
+ }
72
+
73
+ // A person clicking the link in the message.
74
+ route.get('/_stacks/email/unsubscribe/{token}', unsubscribe).skipCsrf()
75
+
76
+ // The mail client's own unsubscribe button. `buildListUnsubscribeHeaders`
77
+ // sends `List-Unsubscribe-Post: List-Unsubscribe=One-Click`, and RFC 8058 has
78
+ // the client POST that body to the same URL. Only GET was mounted, so the
79
+ // button Gmail and Apple Mail show next to the sender reached no route and
80
+ // nobody was unsubscribed.
81
+ route.post('/_stacks/email/unsubscribe/{token}', unsubscribe).skipCsrf()
72
82
 
73
83
  // ============================================================================
74
84
  // Provider webhooks (stacksjs/stacks#1881)
@@ -43,7 +43,9 @@ jobs:
43
43
  node-modules-
44
44
 
45
45
  - name: Install Dependencies
46
- run: bun install
46
+ # Frozen: a lockfile that no longer matches package.json fails here,
47
+ # not in the deploy that installs from it.
48
+ run: bun install --frozen-lockfile
47
49
 
48
50
  - name: Lint
49
51
  run: bun buddy lint
@@ -74,7 +76,9 @@ jobs:
74
76
  node-modules-
75
77
 
76
78
  - name: Install dependencies
77
- run: bun install
79
+ # Frozen: a lockfile that no longer matches package.json fails here,
80
+ # not in the deploy that installs from it.
81
+ run: bun install --frozen-lockfile
78
82
 
79
83
  - name: Set Application Key
80
84
  run: bun buddy key:generate
@@ -108,7 +112,9 @@ jobs:
108
112
  node-modules-
109
113
 
110
114
  - name: Install Dependencies
111
- run: bun install
115
+ # Frozen: a lockfile that no longer matches package.json fails here,
116
+ # not in the deploy that installs from it.
117
+ run: bun install --frozen-lockfile
112
118
 
113
119
  - name: Set Application Key
114
120
  run: bun buddy key:generate