site-vigil-visitors 0.1.0 → 0.1.2
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/bin/init.mjs +124 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +0 -5
- package/dist/core.js.map +1 -1
- package/package.json +5 -1
package/bin/init.mjs
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createInterface } from 'node:readline'
|
|
3
|
+
import { readFile, writeFile, access } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
|
|
6
|
+
const ENDPOINT = 'https://visit-tracker.tithij.workers.dev'
|
|
7
|
+
|
|
8
|
+
const CANDIDATES = [
|
|
9
|
+
'src/App.tsx',
|
|
10
|
+
'src/App.jsx',
|
|
11
|
+
'src/main.tsx',
|
|
12
|
+
'src/main.jsx',
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
async function findAppFile(cwd) {
|
|
16
|
+
for (const candidate of CANDIDATES) {
|
|
17
|
+
try {
|
|
18
|
+
await access(join(cwd, candidate))
|
|
19
|
+
return { path: join(cwd, candidate), rel: candidate }
|
|
20
|
+
} catch {}
|
|
21
|
+
}
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function promptSiteId() {
|
|
26
|
+
const arg = process.argv.find(a => a.startsWith('--site-id='))
|
|
27
|
+
if (arg) return arg.slice('--site-id='.length).trim()
|
|
28
|
+
|
|
29
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
30
|
+
return new Promise(resolve => {
|
|
31
|
+
rl.question('Enter your site ID (e.g. my-website): ', answer => {
|
|
32
|
+
rl.close()
|
|
33
|
+
resolve(answer.trim())
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function patchImports(content) {
|
|
39
|
+
if (content.includes("from 'site-vigil-visitors/react'")) return content
|
|
40
|
+
const matches = [...content.matchAll(/^import .+$/gm)]
|
|
41
|
+
if (!matches.length) return content
|
|
42
|
+
const last = matches.at(-1)
|
|
43
|
+
const pos = last.index + last[0].length
|
|
44
|
+
return (
|
|
45
|
+
content.slice(0, pos) +
|
|
46
|
+
"\nimport { Tracking } from 'site-vigil-visitors/react'" +
|
|
47
|
+
content.slice(pos)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function patchJsx(content, siteId) {
|
|
52
|
+
if (content.includes('<Tracking ')) return content
|
|
53
|
+
|
|
54
|
+
// Match the first non-self-closing JSX opening tag (capital-letter component) and
|
|
55
|
+
// insert <Tracking /> as its first child, matching the sibling's indentation.
|
|
56
|
+
const firstParentTag = /^([ \t]+<[A-Z][^\n]*[^/]>)([ \t]*\n)([ \t]+<)/m
|
|
57
|
+
const m = content.match(firstParentTag)
|
|
58
|
+
if (!m) return null
|
|
59
|
+
|
|
60
|
+
const indent = m[3].match(/^([ \t]+)/)[1]
|
|
61
|
+
const trackingLine = `${indent}<Tracking siteId="${siteId}" endpoint="${ENDPOINT}" />\n`
|
|
62
|
+
return content.replace(firstParentTag, `$1$2${trackingLine}$3`)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function printManual(siteId) {
|
|
66
|
+
console.log(`Add this import to your app entry file:
|
|
67
|
+
|
|
68
|
+
import { Tracking } from 'site-vigil-visitors/react'
|
|
69
|
+
|
|
70
|
+
Then add the component inside your JSX tree:
|
|
71
|
+
|
|
72
|
+
<Tracking
|
|
73
|
+
siteId="${siteId}"
|
|
74
|
+
endpoint="${ENDPOINT}"
|
|
75
|
+
/>
|
|
76
|
+
`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function main() {
|
|
80
|
+
console.log('site-vigil-visitors init\n')
|
|
81
|
+
|
|
82
|
+
const siteId = await promptSiteId()
|
|
83
|
+
if (!siteId) {
|
|
84
|
+
console.error('Error: site ID is required.')
|
|
85
|
+
process.exit(1)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const found = await findAppFile(process.cwd())
|
|
89
|
+
if (!found) {
|
|
90
|
+
console.log('Could not find src/App.tsx or src/main.tsx. Add manually:\n')
|
|
91
|
+
printManual(siteId)
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(`Found: ${found.rel}`)
|
|
96
|
+
|
|
97
|
+
let content = await readFile(found.path, 'utf-8')
|
|
98
|
+
content = patchImports(content)
|
|
99
|
+
const patched = patchJsx(content, siteId)
|
|
100
|
+
|
|
101
|
+
if (!patched) {
|
|
102
|
+
console.log('Could not automatically patch JSX. Add manually:\n')
|
|
103
|
+
printManual(siteId)
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
await writeFile(found.path, patched, 'utf-8')
|
|
108
|
+
|
|
109
|
+
console.log(`
|
|
110
|
+
Done! Added <Tracking /> to ${found.rel}.
|
|
111
|
+
|
|
112
|
+
To verify:
|
|
113
|
+
1. Start your dev server
|
|
114
|
+
2. Open DevTools → Network, filter for "visit-tracker"
|
|
115
|
+
3. Reload — you should see a POST with status 200
|
|
116
|
+
|
|
117
|
+
Note: make sure "${siteId}" is registered in your Supabase websites table (tracking_id column).
|
|
118
|
+
`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
main().catch(err => {
|
|
122
|
+
console.error(err.message)
|
|
123
|
+
process.exit(1)
|
|
124
|
+
})
|
package/dist/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEnD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;CAC/D;AAYD,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,UAA6B,EAC7B,iBAAwB,GACzB,EAAE,aAAa,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEnD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;CAC/D;AAYD,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,UAA6B,EAC7B,iBAAwB,GACzB,EAAE,aAAa,GAAG,OAAO,CA8DzB"}
|
package/dist/core.js
CHANGED
|
@@ -32,11 +32,6 @@ export function createTracker({ siteId, endpoint, sessionKey = 'tithij_session',
|
|
|
32
32
|
...metadata,
|
|
33
33
|
};
|
|
34
34
|
const body = JSON.stringify(payload);
|
|
35
|
-
if (typeof navigator.sendBeacon === 'function') {
|
|
36
|
-
const blob = new Blob([body], { type: 'application/json' });
|
|
37
|
-
navigator.sendBeacon(endpoint, blob);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
35
|
void fetch(endpoint, {
|
|
41
36
|
method: 'POST',
|
|
42
37
|
headers: { 'Content-Type': 'application/json' },
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAgBA,SAAS,eAAe;IACtB,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAEzE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,EAAE,CAAA;IACrB,CAAC;IAED,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAA;AACvE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,UAAU,GAAG,gBAAgB,EAC7B,iBAAiB,GAAG,IAAI,GACV;IACd,MAAM,SAAS,GACb,OAAO,MAAM,KAAK,WAAW;QAC7B,OAAO,QAAQ,KAAK,WAAW;QAC/B,OAAO,SAAS,KAAK,WAAW,CAAA;IAElC,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,IAAI,CAAC,SAAS;YAAE,OAAO,QAAQ,CAAA;QAE/B,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAC1D,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAE7B,MAAM,EAAE,GAAG,eAAe,EAAE,CAAA;QAC5B,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QAC7C,OAAO,EAAE,CAAA;IACX,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,WAA0B,EAAE,EAAE,EAAE;QAC5D,IAAI,CAAC,SAAS;YAAE,OAAM;QAEtB,MAAM,OAAO,GAAG;YACd,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;YAC9B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM;YACN,SAAS,EAAE,YAAY,EAAE;YACzB,GAAG,QAAQ;SACZ,CAAA;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAEpC,
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAgBA,SAAS,eAAe;IACtB,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAEzE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,EAAE,CAAA;IACrB,CAAC;IAED,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAA;AACvE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,UAAU,GAAG,gBAAgB,EAC7B,iBAAiB,GAAG,IAAI,GACV;IACd,MAAM,SAAS,GACb,OAAO,MAAM,KAAK,WAAW;QAC7B,OAAO,QAAQ,KAAK,WAAW;QAC/B,OAAO,SAAS,KAAK,WAAW,CAAA;IAElC,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,IAAI,CAAC,SAAS;YAAE,OAAO,QAAQ,CAAA;QAE/B,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAC1D,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAE7B,MAAM,EAAE,GAAG,eAAe,EAAE,CAAA;QAC5B,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QAC7C,OAAO,EAAE,CAAA;IACX,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,WAA0B,EAAE,EAAE,EAAE;QAC5D,IAAI,CAAC,SAAS;YAAE,OAAM;QAEtB,MAAM,OAAO,GAAG;YACd,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;YAC9B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM;YACN,SAAS,EAAE,YAAY,EAAE;YACzB,GAAG,QAAQ;SACZ,CAAA;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAEpC,KAAK,KAAK,CAAC,QAAQ,EAAE;YACnB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI;YACJ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACpB,CAAC,CAAA;IAED,MAAM,kBAAkB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAE9C,OAAO;QACL,KAAK;YACH,IAAI,CAAC,OAAO,CAAC,CAAA;YAEb,IAAI,iBAAiB,IAAI,SAAS,EAAE,CAAC;gBACnC,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;YAC7D,CAAC;QACH,CAAC;QACD,OAAO;YACL,IAAI,iBAAiB,IAAI,SAAS,EAAE,CAAC;gBACnC,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;YAChE,CAAC;QACH,CAAC;QACD,aAAa;YACX,IAAI,CAAC,OAAO,CAAC,CAAA;QACf,CAAC;QACD,UAAU,CAAC,MAAc,EAAE,WAA0B,EAAE;YACrD,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACxB,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "site-vigil-visitors",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Lightweight browser visit tracking with optional React integration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,8 +18,12 @@
|
|
|
18
18
|
"import": "./dist/react.js"
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"site-vigil-visitors": "bin/init.mjs"
|
|
23
|
+
},
|
|
21
24
|
"files": [
|
|
22
25
|
"dist",
|
|
26
|
+
"bin",
|
|
23
27
|
"README.md",
|
|
24
28
|
"LICENSE"
|
|
25
29
|
],
|