ReviewOS

also looking at this

stacks/ts-analytics

fix: emit a real library build (dist/index.js + ./stx) so the package is importable

#124
Merged glennmichael123 wants to merge fix/library-build into main
6 files +72 -13
.gitignoremodified+1-0
Changes to .gitignore
@@ -5,6 +5,7 @@
55*.tgz
66coverage
77dist
8dist-site
89lib-cov
910logs
1011node_modules
build-site.tsadded+17-0
Changes to build-site.ts
@@ -0,0 +1,17 @@
1#!/usr/bin/env bun
2/**
3 * Static dashboard SITE build (deploy artifact for Netlify / Vercel / S3) →
4 * dist-site/. This is NOT the npm package output — the importable library is
5 * built by build.ts (`bun run build`) into dist/.
6 *
7 * Run with `bun run build:site`.
8 */
9import { generateStaticSite } from '@stacksjs/stx/ssg'
10
11await generateStaticSite({
12 pagesDir: 'pages',
13 outputDir: 'dist-site',
14 publicDir: 'public',
15 sitemap: true,
16 cleanOutput: true,
17})
build.tsmodified+44-8
Changes to build.ts
@@ -1,10 +1,46 @@
11#!/usr/bin/env bun
2import { generateStaticSite } from '@stacksjs/stx/ssg'
3
4await generateStaticSite({
5 pagesDir: 'pages',
6 outputDir: 'dist',
7 publicDir: 'public',
8 sitemap: true,
9 cleanOutput: true,
2/**
3 * Library build — emits the package's JS + declarations so `@stacksjs/ts-analytics`
4 * is importable (package.json's `module`/`exports`/`types` all point at ./dist).
5 *
6 * Builds two entrypoints so both exports resolve:
7 * `.` → dist/index.js + dist/index.d.ts
8 * `./stx` → dist/integrations/stx.js + dist/integrations/stx.d.ts (the tsAnalytics() module)
9 *
10 * The static dashboard SITE is a separate deploy artifact — `bun run build:site`
11 * (build-site.ts → dist-site/). Keeping them apart stops the SSG's cleanOutput
12 * from wiping the library and vice-versa. node_modules stays external.
13 */
14import { rmSync } from 'node:fs'
15import { dts } from 'bun-plugin-dtsx'
16import stx from 'bun-plugin-stx'
17
18rmSync('./dist', { recursive: true, force: true })
19
20const result = await Bun.build({
21 entrypoints: ['./src/index.ts', './src/integrations/stx.ts'],
22 splitting: true,
23 outdir: './dist',
24 root: './src',
25 // bun-plugin-stx resolves the `.stx` imports a few library modules carry
26 // (e.g. handlers render dashboard views server-side); dts() emits declarations.
27 plugins: [stx(), dts()],
28 target: 'bun',
29 format: 'esm',
30 packages: 'external',
1031})
32
33if (!result.success) {
34 console.error('[ts-analytics] library build failed:')
35 for (const log of result.logs)
36 console.error(log)
37 process.exit(1)
38}
39
40for (const f of ['./dist/index.js', './dist/integrations/stx.js']) {
41 if (!(await Bun.file(f).exists())) {
42 console.error(`[ts-analytics] build succeeded but ${f} is missing — check the entrypoints/exports`)
43 process.exit(1)
44 }
45}
46console.log(`[ts-analytics] library built → dist/ (${result.outputs.length} files; index.js + integrations/stx.js present)`)
package.jsonmodified+1-0
Changes to package.json
@@ -46,6 +46,7 @@
4646 "scripts": {
4747 "analytics": "bun ./bin/cli.ts",
4848 "build": "bun build.ts",
49 "build:site": "bun build-site.ts",
4950 "preview": "bun preview.ts",
5051 "dev": "bun --watch serve.ts",
5152 "dev:server": "bun --watch ./server/index.ts",
preview.tsmodified+4-3
Changes to preview.ts
@@ -1,13 +1,14 @@
11#!/usr/bin/env bun
22/**
3 * Serves the static `dist/` build locally for testing before deploying
4 * to Netlify / Vercel / S3. Plain file server, no processing.
3 * Serves the static site build (`dist-site/`, produced by `bun run build:site`)
4 * locally for testing before deploying to Netlify / Vercel / S3. Plain file
5 * server, no processing. (The npm library build lives in `dist/` — see build.ts.)
56 *
67 * Usage: bun run preview
78 */
89
910const port = Number(process.argv[2]) || 3001
10const distDir = 'dist'
11const distDir = 'dist-site'
1112
1213Bun.serve({
1314 port,
src/tracking-script.tsmodified+5-2
Changes to src/tracking-script.ts
@@ -187,10 +187,13 @@ function buildScript(config: TrackingScriptConfig): string {
187187}
188188
189189function buildConfigSection(config: TrackingScriptConfig): string {
190 // JSON.stringify the string values (matching excludePaths below) so a quote,
191 // backslash, or newline in siteId/apiEndpoint can't break out of the literal
192 // and corrupt the whole inline tracker.
190193 return `// Configuration
191194var CONFIG = {
192 siteId: '${config.siteId}',
193 endpoint: '${config.apiEndpoint}/collect',
195 siteId: ${JSON.stringify(config.siteId)},
196 endpoint: ${JSON.stringify(`${config.apiEndpoint}/collect`)},
194197 honorDnt: ${config.honorDnt ?? true},
195198 sessionTimeout: ${(config.sessionTimeout ?? 30) * 60 * 1000},
196199 debug: ${config.debug ?? false},