Skip to content

Commit c7f3b20

Browse files
committed
fix: typecheck issues after demo merge
1 parent b95ca15 commit c7f3b20

File tree

9 files changed

+114
-43
lines changed

9 files changed

+114
-43
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
name: pnpm-postinstall-deps
3+
description: Use when user adds package with postinstall script (supabase, sharp), gets "binary not found" errors in CI, or asks about onlyBuiltDependencies. Explains the two-step pattern for managing packages that need build/postinstall scripts in pnpm workspaces with frozen lockfiles.
4+
---
5+
6+
# pnpm Postinstall Dependencies
7+
8+
Manage packages that need postinstall scripts in pnpm workspaces.
9+
10+
## The Problem
11+
12+
`pnpm install --frozen-lockfile --prefer-offline` in CI restores from cache and skips postinstall scripts. Packages like `supabase` download binaries via postinstall - without it, the binary doesn't exist.
13+
14+
## The Pattern
15+
16+
**Two-step sync required:**
17+
18+
1. **pnpm-workspace.yaml** - Declares which packages are allowed to run build scripts
19+
2. **Setup action** - Explicitly rebuilds those packages after install
20+
21+
<critical>
22+
Both lists MUST stay in sync. If they diverge:
23+
- Missing in yaml → Package can't run postinstall (security)
24+
- Missing in action → Binary won't be available in CI
25+
</critical>
26+
27+
## Checklist
28+
29+
When adding a package that needs postinstall:
30+
31+
### 1. Add to pnpm-workspace.yaml
32+
33+
```yaml
34+
onlyBuiltDependencies:
35+
- supabase
36+
- sharp
37+
- your-new-package # Add here
38+
```
39+
40+
### 2. Update .github/actions/setup/action.yml
41+
42+
```yaml
43+
- name: Rebuild packages that need postinstall (onlyBuiltDependencies)
44+
shell: bash
45+
run: pnpm rebuild supabase sharp your-new-package # Add here
46+
```
47+
48+
### 3. Verify
49+
50+
Check both files have identical package lists.
51+
52+
## Why Explicit Package Names?
53+
54+
`pnpm rebuild --pending` is too implicit - unclear if it respects onlyBuiltDependencies. Explicit names guarantee behavior and make configuration visible.
55+
56+
## Common Packages
57+
58+
- `supabase` - Downloads CLI binary from GitHub releases
59+
- `sharp` - Builds native image processing library
60+
- `esbuild` - Downloads platform-specific binary
61+
- `puppeteer` - Downloads Chromium binary
Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
/**
22
* Cloudflare Worker for Plausible Analytics Proxy
33
*
4-
* IMPORTANT: You MUST update the ProxyScript variable below with your
5-
* actual Plausible script URL from your dashboard before deploying!
4+
* This worker proxies Plausible Analytics scripts and events to avoid ad-blocker detection
65
*/
76

8-
// CONFIGURATION - UPDATE THIS VALUE!
9-
// Get this from your Plausible dashboard (Site Settings > Site Installation)
10-
// It will look like: https://plausible.io/js/script.js (or pa-XXXXX.js for custom domains)
11-
const ProxyScript = 'https://plausible.io/js/script.js'; // ← UPDATE THIS!
12-
137
// Customize these paths to avoid ad-blocker detection
148
const ScriptName = '/stats/script.js';
159
const Endpoint = '/stats/event';
@@ -18,34 +12,39 @@ const Endpoint = '/stats/event';
1812
const ScriptWithoutExtension = ScriptName.replace('.js', '');
1913

2014
addEventListener('fetch', (event) => {
21-
event.passThroughOnException();
22-
event.respondWith(handleRequest(event));
15+
event.passThroughOnException();
16+
event.respondWith(handleRequest(event));
2317
});
2418

2519
async function handleRequest(event) {
26-
const pathname = new URL(event.request.url).pathname;
27-
const [baseUri] = pathname.split('.');
20+
const pathname = new URL(event.request.url).pathname;
21+
const [baseUri, ...extensions] = pathname.split('.');
2822

29-
if (baseUri.endsWith(ScriptWithoutExtension)) {
30-
return getScript(event);
31-
} else if (pathname.endsWith(Endpoint)) {
32-
return postData(event);
33-
}
23+
if (baseUri.endsWith(ScriptWithoutExtension)) {
24+
return getScript(event, extensions);
25+
} else if (pathname.endsWith(Endpoint)) {
26+
return postData(event);
27+
}
3428

35-
return new Response(null, { status: 404 });
29+
return new Response(null, { status: 404 });
3630
}
3731

38-
async function getScript(event) {
39-
let response = await caches.default.match(event.request);
40-
if (!response) {
41-
response = await fetch(ProxyScript);
42-
event.waitUntil(caches.default.put(event.request, response.clone()));
43-
}
44-
return response;
32+
async function getScript(event, extensions) {
33+
let response = await caches.default.match(event.request);
34+
if (!response) {
35+
// Fetch the standard Plausible script with any extensions
36+
// Default to 'plausible.js' if no extensions are provided
37+
const scriptPath = extensions.length > 0
38+
? 'plausible.' + extensions.join('.')
39+
: 'plausible.js';
40+
response = await fetch('https://plausible.io/js/' + scriptPath);
41+
event.waitUntil(caches.default.put(event.request, response.clone()));
42+
}
43+
return response;
4544
}
4645

4746
async function postData(event) {
48-
const request = new Request(event.request);
49-
request.headers.delete('cookie');
50-
return await fetch('https://plausible.io/api/event', request);
51-
}
47+
const request = new Request(event.request);
48+
request.headers.delete('cookie');
49+
return await fetch('https://plausible.io/api/event', request);
50+
}

apps/demo/src/lib/components/ExplanationPanel.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,17 @@
5050
explanation:
5151
'Unique identifier for this flow. Must be ≤128 characters, containing only letters, numbers, and underscores.'
5252
},
53-
{
54-
name: 'maxAttempts',
55-
value: '2',
56-
explanation:
57-
'Maximum total attempts allowed. With 2 attempts: 1 initial try + 1 retry on failure.'
58-
},
5953
{
6054
name: 'baseDelay',
6155
value: '1',
6256
explanation:
6357
'Base delay for retries in seconds. With exponential backoff, first retry waits 1s (subsequent retries would wait 2s, 4s, etc).'
58+
},
59+
{
60+
name: 'maxAttempts',
61+
value: '2',
62+
explanation:
63+
'Maximum total attempts allowed. With 2 attempts: 1 initial try + 1 retry on failure.'
6464
}
6565
],
6666
inputType: `{

apps/demo/src/lib/data/flow-code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const FLOW_SECTIONS: Record<string, CodeSection> = {
1919
flow_config: {
2020
code: `new Flow<{ url: string }>({
2121
slug: 'article_flow',
22-
baseDelay:1,
22+
baseDelay: 1,
2323
maxAttempts: 2
2424
})`
2525
},

apps/demo/src/routes/+layout.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
<script
1111
defer
1212
data-domain="demo.pgflow.dev"
13-
data-api="https://pgflow-demo-edge.jumski.workers.dev/stats/api/event"
14-
src="https://plausible.io/js/script.js"
13+
data-api="https://pgflow-demo-edge.jumski.workers.dev/stats/event"
14+
src="https://pgflow-demo-edge.jumski.workers.dev/stats/script.js"
1515
></script>
1616
</svelte:head>
1717

apps/demo/src/routes/+page.svelte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@
571571
<div class="flex items-center gap-2 md:gap-3">
572572
<a
573573
href="https://pgflow.dev"
574+
target="_blank"
575+
rel="noopener noreferrer"
574576
class="flex items-center gap-1.5 md:gap-2"
575577
onclick={() => track('Logo Clicked', { location: 'header' })}
576578
>
@@ -580,6 +582,8 @@
580582
<span class="text-muted-foreground text-xs">|</span>
581583
<a
582584
href="https://pgflow.dev"
585+
target="_blank"
586+
rel="noopener noreferrer"
583587
class="text-xs text-muted-foreground hover:text-foreground"
584588
onclick={() =>
585589
track('External Link Clicked', { destination: 'website', location: 'header' })}
@@ -588,6 +592,8 @@
588592
<span class="text-muted-foreground text-xs">|</span>
589593
<a
590594
href="https://github.com/pgflow-dev/pgflow"
595+
target="_blank"
596+
rel="noopener noreferrer"
591597
class="text-xs text-muted-foreground hover:text-foreground"
592598
onclick={() =>
593599
track('External Link Clicked', { destination: 'github', location: 'header' })}

apps/demo/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"skipLibCheck": true,
1010
"sourceMap": true,
1111
"strict": true,
12-
"moduleResolution": "bundler"
12+
"moduleResolution": "bundler",
13+
"composite": true
1314
},
1415
"references": [
1516
{

pkgs/client/vite.config.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@ export default defineConfig({
77
root: __dirname,
88
cacheDir: '../../node_modules/.vite/pkgs/client',
99
plugins: [
10-
dts({
10+
dts({
1111
include: ['src/**/*.ts'],
1212
outDir: 'dist',
1313
rollupTypes: false, // Don't bundle for now
1414
insertTypesEntry: true,
15-
tsConfigFilePath: resolve(__dirname, 'tsconfig.lib.json'),
16-
skipDiagnostics: true // Skip TypeScript diagnostics to avoid vite-plugin-dts errors with monorepo project references.
17-
// The plugin tries to compile all imported files (including from other packages)
15+
tsconfigPath: resolve(__dirname, 'tsconfig.lib.json'),
16+
skipDiagnostics: true // Skip TypeScript diagnostics to avoid vite-plugin-dts errors with monorepo project references.
17+
// The plugin tries to compile all imported files (including from other packages)
1818
// which breaks rootDir boundaries. Nx runs proper type checking separately.
19-
})
19+
}) as any // Type cast to avoid Vite version mismatch between packages
20+
2021
],
2122
build: {
2223
lib: {

tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
},
2121
{
2222
"path": "./pkgs/client"
23+
},
24+
{
25+
"path": "./apps/demo"
2326
}
2427
]
2528
}

0 commit comments

Comments
 (0)