@jayfarei/lazyanalytics 0.1.0
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 +27 -0
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/cli/dist/commands/base.d.ts +2 -0
- package/cli/dist/commands/base.js +129 -0
- package/cli/dist/commands/config.d.ts +2 -0
- package/cli/dist/commands/config.js +45 -0
- package/cli/dist/commands/setup.d.ts +2 -0
- package/cli/dist/commands/setup.js +155 -0
- package/cli/dist/commands/sites.d.ts +2 -0
- package/cli/dist/commands/sites.js +127 -0
- package/cli/dist/commands/skill.d.ts +2 -0
- package/cli/dist/commands/skill.js +28 -0
- package/cli/dist/commands/snippet.d.ts +2 -0
- package/cli/dist/commands/snippet.js +48 -0
- package/cli/dist/commands/usage.d.ts +2 -0
- package/cli/dist/commands/usage.js +156 -0
- package/cli/dist/index.d.ts +2 -0
- package/cli/dist/index.js +31 -0
- package/cli/dist/lib/api.d.ts +9 -0
- package/cli/dist/lib/api.js +27 -0
- package/cli/dist/lib/env.d.ts +15 -0
- package/cli/dist/lib/env.js +81 -0
- package/cli/dist/lib/paths.d.ts +16 -0
- package/cli/dist/lib/paths.js +54 -0
- package/cli/dist/lib/prompt.d.ts +8 -0
- package/cli/dist/lib/prompt.js +42 -0
- package/cli/dist/lib/scaffold.d.ts +5 -0
- package/cli/dist/lib/scaffold.js +21 -0
- package/cli/dist/lib/wrangler.d.ts +17 -0
- package/cli/dist/lib/wrangler.js +65 -0
- package/dist/worker.js +3221 -0
- package/package.json +58 -0
- package/skill/SKILL.md +111 -0
- package/templates/wrangler.toml +14 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline';
|
|
2
|
+
import { Writable } from 'node:stream';
|
|
3
|
+
/** Ask a question on the terminal. Returns the trimmed answer. */
|
|
4
|
+
export function prompt(question) {
|
|
5
|
+
return new Promise((resolve) => {
|
|
6
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7
|
+
rl.question(question, (answer) => {
|
|
8
|
+
rl.close();
|
|
9
|
+
resolve(answer.trim());
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/** Ask for a secret without echoing the typed characters. */
|
|
14
|
+
export function promptHidden(question) {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
let muted = false;
|
|
17
|
+
const mutedOutput = new Writable({
|
|
18
|
+
write(chunk, _enc, cb) {
|
|
19
|
+
if (!muted)
|
|
20
|
+
process.stdout.write(chunk);
|
|
21
|
+
cb();
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
const rl = createInterface({ input: process.stdin, output: mutedOutput, terminal: true });
|
|
25
|
+
rl.question(question, (answer) => {
|
|
26
|
+
muted = false;
|
|
27
|
+
rl.close();
|
|
28
|
+
process.stdout.write('\n');
|
|
29
|
+
resolve(answer.trim());
|
|
30
|
+
});
|
|
31
|
+
muted = true;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** Validate a bare domain name (e.g. example.com, blog.example.co.uk). */
|
|
35
|
+
export function isValidDomain(domain) {
|
|
36
|
+
return /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$/i.test(domain);
|
|
37
|
+
}
|
|
38
|
+
/** Build the tracking snippet for a site. */
|
|
39
|
+
export function trackingSnippet(apiUrl, site) {
|
|
40
|
+
const base = apiUrl.replace(/\/$/, '');
|
|
41
|
+
return `<script defer id="analytics" data-site-id="${site}" src="${base}/tracker.js"></script>`;
|
|
42
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const SCAFFOLD_WRANGLER_TOML: string;
|
|
2
|
+
/** Read ALLOWED_SITES back out of a scaffolded wrangler.toml, if present. */
|
|
3
|
+
export declare function readAllowedSites(path?: string): string[];
|
|
4
|
+
/** Rewrite the ALLOWED_SITES line in a scaffolded wrangler.toml. */
|
|
5
|
+
export declare function writeAllowedSites(sites: string[], path?: string): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { WORKER_SCAFFOLD_DIR } from './env.js';
|
|
4
|
+
export const SCAFFOLD_WRANGLER_TOML = join(WORKER_SCAFFOLD_DIR, 'wrangler.toml');
|
|
5
|
+
/** Read ALLOWED_SITES back out of a scaffolded wrangler.toml, if present. */
|
|
6
|
+
export function readAllowedSites(path = SCAFFOLD_WRANGLER_TOML) {
|
|
7
|
+
if (!existsSync(path))
|
|
8
|
+
return [];
|
|
9
|
+
const match = readFileSync(path, 'utf-8').match(/^ALLOWED_SITES\s*=\s*"([^"]*)"/m);
|
|
10
|
+
if (!match || !match[1])
|
|
11
|
+
return [];
|
|
12
|
+
return match[1].split(',').map((s) => s.trim()).filter(Boolean);
|
|
13
|
+
}
|
|
14
|
+
/** Rewrite the ALLOWED_SITES line in a scaffolded wrangler.toml. */
|
|
15
|
+
export function writeAllowedSites(sites, path = SCAFFOLD_WRANGLER_TOML) {
|
|
16
|
+
const content = readFileSync(path, 'utf-8');
|
|
17
|
+
if (!/^ALLOWED_SITES\s*=/m.test(content)) {
|
|
18
|
+
throw new Error(`No ALLOWED_SITES line found in ${path}`);
|
|
19
|
+
}
|
|
20
|
+
writeFileSync(path, content.replace(/^ALLOWED_SITES\s*=\s*"[^"]*"/m, `ALLOWED_SITES = "${sites.join(',')}"`));
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface WranglerEnv {
|
|
2
|
+
CLOUDFLARE_API_TOKEN: string;
|
|
3
|
+
CLOUDFLARE_ACCOUNT_ID: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Run `npx wrangler@4 deploy` in `cwd`, streaming output to the terminal
|
|
7
|
+
* (stderr, so stdout stays clean for JSON) while capturing stdout so the
|
|
8
|
+
* workers.dev URL can be parsed.
|
|
9
|
+
*/
|
|
10
|
+
export declare function wranglerDeploy(cwd: string, env: WranglerEnv): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Run `npx wrangler@4 secret put <name>` in `cwd`, piping the secret value
|
|
13
|
+
* via stdin. The value is never echoed or logged.
|
|
14
|
+
*/
|
|
15
|
+
export declare function wranglerSecretPut(cwd: string, env: WranglerEnv, name: string, value: string): Promise<void>;
|
|
16
|
+
/** Parse the workers.dev URL from wrangler deploy output. Returns null if absent. */
|
|
17
|
+
export declare function parseWorkersDevUrl(deployOutput: string): string | null;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
// On Windows npx is a .cmd shim that spawn() can't execute directly.
|
|
3
|
+
const NPX = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
4
|
+
function wranglerProcessEnv(env) {
|
|
5
|
+
return {
|
|
6
|
+
...process.env,
|
|
7
|
+
CLOUDFLARE_API_TOKEN: env.CLOUDFLARE_API_TOKEN,
|
|
8
|
+
CLOUDFLARE_ACCOUNT_ID: env.CLOUDFLARE_ACCOUNT_ID,
|
|
9
|
+
// Keep wrangler non-interactive and quiet about updates/telemetry prompts
|
|
10
|
+
WRANGLER_SEND_METRICS: 'false',
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run `npx wrangler@4 deploy` in `cwd`, streaming output to the terminal
|
|
15
|
+
* (stderr, so stdout stays clean for JSON) while capturing stdout so the
|
|
16
|
+
* workers.dev URL can be parsed.
|
|
17
|
+
*/
|
|
18
|
+
export function wranglerDeploy(cwd, env) {
|
|
19
|
+
return new Promise((resolvePromise, reject) => {
|
|
20
|
+
const child = spawn(NPX, ['wrangler@4', 'deploy'], {
|
|
21
|
+
cwd,
|
|
22
|
+
env: wranglerProcessEnv(env),
|
|
23
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
24
|
+
});
|
|
25
|
+
let stdout = '';
|
|
26
|
+
child.stdout.on('data', (chunk) => {
|
|
27
|
+
stdout += chunk.toString();
|
|
28
|
+
process.stderr.write(chunk);
|
|
29
|
+
});
|
|
30
|
+
child.on('error', reject);
|
|
31
|
+
child.on('close', (code) => {
|
|
32
|
+
if (code === 0)
|
|
33
|
+
resolvePromise(stdout);
|
|
34
|
+
else
|
|
35
|
+
reject(new Error(`wrangler deploy exited with code ${code}`));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run `npx wrangler@4 secret put <name>` in `cwd`, piping the secret value
|
|
41
|
+
* via stdin. The value is never echoed or logged.
|
|
42
|
+
*/
|
|
43
|
+
export function wranglerSecretPut(cwd, env, name, value) {
|
|
44
|
+
return new Promise((resolvePromise, reject) => {
|
|
45
|
+
const child = spawn(NPX, ['wrangler@4', 'secret', 'put', name], {
|
|
46
|
+
cwd,
|
|
47
|
+
env: wranglerProcessEnv(env),
|
|
48
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
49
|
+
});
|
|
50
|
+
child.stdin.write(value + '\n');
|
|
51
|
+
child.stdin.end();
|
|
52
|
+
child.on('error', reject);
|
|
53
|
+
child.on('close', (code) => {
|
|
54
|
+
if (code === 0)
|
|
55
|
+
resolvePromise();
|
|
56
|
+
else
|
|
57
|
+
reject(new Error(`wrangler secret put ${name} exited with code ${code}`));
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** Parse the workers.dev URL from wrangler deploy output. Returns null if absent. */
|
|
62
|
+
export function parseWorkersDevUrl(deployOutput) {
|
|
63
|
+
const match = deployOutput.match(/https:\/\/[a-z0-9-]+(\.[a-z0-9-]+)*\.workers\.dev/i);
|
|
64
|
+
return match ? match[0] : null;
|
|
65
|
+
}
|