@hasna/shortlinks 0.1.9 → 0.1.10

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.
@@ -0,0 +1,90 @@
1
+ export interface Domain {
2
+ id: string;
3
+ hostname: string;
4
+ provider: string;
5
+ default_domain: boolean;
6
+ cloudflare_zone_id: string | null;
7
+ cloudflare_account_id: string | null;
8
+ cloudflare_worker_name: string | null;
9
+ origin_url: string | null;
10
+ notes: string | null;
11
+ metadata: Record<string, unknown>;
12
+ machine_id: string | null;
13
+ synced_at: string | null;
14
+ created_at: string;
15
+ updated_at: string;
16
+ }
17
+ export interface Link {
18
+ id: string;
19
+ domain_id: string;
20
+ hostname: string;
21
+ slug: string;
22
+ destination_url: string;
23
+ title: string | null;
24
+ active: boolean;
25
+ expires_at: string | null;
26
+ metadata: Record<string, unknown>;
27
+ machine_id: string | null;
28
+ synced_at: string | null;
29
+ created_at: string;
30
+ updated_at: string;
31
+ short_url?: string;
32
+ }
33
+ export interface Click {
34
+ id: string;
35
+ link_id: string;
36
+ domain_id: string;
37
+ slug: string;
38
+ clicked_at: string;
39
+ ip_hash: string | null;
40
+ user_agent: string | null;
41
+ referer: string | null;
42
+ country: string | null;
43
+ city: string | null;
44
+ metadata: Record<string, unknown>;
45
+ machine_id: string | null;
46
+ synced_at: string | null;
47
+ created_at: string;
48
+ updated_at: string;
49
+ }
50
+ export interface LinkStats {
51
+ link: Link;
52
+ clicks: number;
53
+ last_clicked_at: string | null;
54
+ top_referrers: Array<{
55
+ referer: string | null;
56
+ clicks: number;
57
+ }>;
58
+ top_user_agents: Array<{
59
+ user_agent: string | null;
60
+ clicks: number;
61
+ }>;
62
+ }
63
+ export interface CreateLinkInput {
64
+ destinationUrl: string;
65
+ domain?: string;
66
+ slug?: string;
67
+ title?: string;
68
+ expiresAt?: string;
69
+ metadata?: Record<string, unknown>;
70
+ slugLength?: number;
71
+ }
72
+ export interface AddDomainInput {
73
+ hostname: string;
74
+ provider?: string;
75
+ defaultDomain?: boolean;
76
+ cloudflareZoneId?: string;
77
+ cloudflareAccountId?: string;
78
+ cloudflareWorkerName?: string;
79
+ originUrl?: string;
80
+ notes?: string;
81
+ metadata?: Record<string, unknown>;
82
+ }
83
+ export interface ClickInput {
84
+ ip?: string | null;
85
+ userAgent?: string | null;
86
+ referer?: string | null;
87
+ country?: string | null;
88
+ city?: string | null;
89
+ metadata?: Record<string, unknown>;
90
+ }
@@ -4,9 +4,15 @@ set -euo pipefail
4
4
  export AWS_REGION="${AWS_REGION:-us-east-1}"
5
5
  export SHORTLINKS_HOME="/var/lib/shortlinks"
6
6
  export SHORTLINKS_PACKAGE="@hasna/shortlinks@latest"
7
- export RDS_SECRET_ID="rds!db-7a451ce6-83a9-40fa-b24a-81e5d5943511"
8
- export RDS_HOST="hasnaxyz-prod-opensource.c4limg0qgqvk.us-east-1.rds.amazonaws.com"
9
- export RDS_USERNAME="hasna_admin"
7
+ export RDS_SECRET_ID="${RDS_SECRET_ID:-}"
8
+ export RDS_HOST="${RDS_HOST:-}"
9
+ export RDS_USERNAME="${RDS_USERNAME:-}"
10
+ export SHORTLINKS_DOMAIN="${SHORTLINKS_DOMAIN:-}"
11
+
12
+ : "${RDS_SECRET_ID:?Set RDS_SECRET_ID to the AWS Secrets Manager secret for the PostgreSQL password}"
13
+ : "${RDS_HOST:?Set RDS_HOST to the PostgreSQL host}"
14
+ : "${RDS_USERNAME:?Set RDS_USERNAME to the PostgreSQL username}"
15
+ : "${SHORTLINKS_DOMAIN:?Set SHORTLINKS_DOMAIN to the public host served by Caddy}"
10
16
 
11
17
  dnf update -y
12
18
  dnf install -y awscli jq tar gzip shadow-utils libcap
@@ -15,28 +21,27 @@ if ! id shortlinks >/dev/null 2>&1; then
15
21
  useradd --system --create-home --home-dir "${SHORTLINKS_HOME}" --shell /sbin/nologin shortlinks
16
22
  fi
17
23
 
18
- install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/cloud"
24
+ install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/shortlinks/cloud"
19
25
  install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/shortlinks"
20
26
 
21
- cat > "${SHORTLINKS_HOME}/.hasna/cloud/config.json" <<CLOUD_CONFIG
27
+ cat > "${SHORTLINKS_HOME}/.hasna/shortlinks/cloud/config.json" <<CLOUD_CONFIG
22
28
  {
23
29
  "rds": {
24
30
  "host": "${RDS_HOST}",
25
31
  "port": 5432,
26
32
  "username": "${RDS_USERNAME}",
27
- "password_env": "HASNA_RDS_PASSWORD",
33
+ "password_env": "SHORTLINKS_CLOUD_DATABASE_PASSWORD",
28
34
  "ssl": true
29
35
  },
30
36
  "mode": "hybrid",
31
- "feedback_endpoint": "https://feedback.hasna.com/api/v1/feedback",
32
37
  "auto_sync_interval_minutes": 0,
33
38
  "sync": {
34
39
  "schedule_minutes": 0
35
40
  }
36
41
  }
37
42
  CLOUD_CONFIG
38
- chown shortlinks:shortlinks "${SHORTLINKS_HOME}/.hasna/cloud/config.json"
39
- chmod 600 "${SHORTLINKS_HOME}/.hasna/cloud/config.json"
43
+ chown shortlinks:shortlinks "${SHORTLINKS_HOME}/.hasna/shortlinks/cloud/config.json"
44
+ chmod 600 "${SHORTLINKS_HOME}/.hasna/shortlinks/cloud/config.json"
40
45
 
41
46
  su -s /bin/bash shortlinks -c 'curl -fsSL https://bun.sh/install | bash'
42
47
  su -s /bin/bash shortlinks -c "${SHORTLINKS_HOME}/.bun/bin/bun install -g ${SHORTLINKS_PACKAGE} --no-cache"
@@ -50,14 +55,16 @@ export HOME="/var/lib/shortlinks"
50
55
  export PATH="/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin"
51
56
  export NODE_TLS_REJECT_UNAUTHORIZED="0"
52
57
 
58
+ : "${RDS_SECRET_ID:?Set RDS_SECRET_ID to the AWS Secrets Manager secret for the PostgreSQL password}"
59
+
53
60
  secret_json="$(aws secretsmanager get-secret-value \
54
61
  --region "${AWS_REGION}" \
55
- --secret-id "rds!db-7a451ce6-83a9-40fa-b24a-81e5d5943511" \
62
+ --secret-id "${RDS_SECRET_ID}" \
56
63
  --query SecretString \
57
64
  --output text)"
58
65
 
59
- export HASNA_RDS_PASSWORD
60
- HASNA_RDS_PASSWORD="$(jq -r '.password' <<<"${secret_json}")"
66
+ export SHORTLINKS_CLOUD_DATABASE_PASSWORD
67
+ SHORTLINKS_CLOUD_DATABASE_PASSWORD="$(jq -r '.password' <<<"${secret_json}")"
61
68
 
62
69
  exec "$@"
63
70
  RUNNER
@@ -66,6 +73,15 @@ chown root:shortlinks /usr/local/bin/shortlinks-env-exec
66
73
 
67
74
  su -s /bin/bash shortlinks -c 'PATH=/var/lib/shortlinks/.bun/bin:$PATH shortlinks --version'
68
75
 
76
+ cat > /etc/default/shortlinks <<SHORTLINKS_ENV
77
+ AWS_REGION=${AWS_REGION}
78
+ RDS_SECRET_ID=${RDS_SECRET_ID}
79
+ SHORTLINKS_DOMAIN=${SHORTLINKS_DOMAIN}
80
+ SHORTLINKS_STORE=cloud
81
+ SHORTLINKS_ENV
82
+ chmod 640 /etc/default/shortlinks
83
+ chown root:shortlinks /etc/default/shortlinks
84
+
69
85
  caddy_version="$(curl -fsSL https://api.github.com/repos/caddyserver/caddy/releases/latest | jq -r '.tag_name // "v2.10.2"' | sed 's/^v//')"
70
86
  case "$(uname -m)" in
71
87
  aarch64|arm64) caddy_arch="arm64" ;;
@@ -90,8 +106,8 @@ Group=shortlinks
90
106
  WorkingDirectory=/var/lib/shortlinks
91
107
  Environment=HOME=/var/lib/shortlinks
92
108
  Environment=PATH=/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin
93
- Environment=SHORTLINKS_STORE=cloud
94
- ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks serve --cloud --host 127.0.0.1 --port 8787 --default-host has.na
109
+ EnvironmentFile=/etc/default/shortlinks
110
+ ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks serve --cloud --host 127.0.0.1 --port 8787 --default-host ${SHORTLINKS_DOMAIN}
95
111
  Restart=always
96
112
  RestartSec=5
97
113
 
@@ -123,8 +139,8 @@ WantedBy=multi-user.target
123
139
  SERVICE
124
140
 
125
141
  install -d /etc/caddy
126
- cat > /etc/caddy/Caddyfile <<'CADDY'
127
- has.na {
142
+ cat > /etc/caddy/Caddyfile <<CADDY
143
+ ${SHORTLINKS_DOMAIN} {
128
144
  encode zstd gzip
129
145
  reverse_proxy 127.0.0.1:8787
130
146
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hasna/shortlinks",
3
- "version": "0.1.9",
4
- "description": "CLI-only shortlink manager for custom domains, click tracking, Cloudflare setup, and @hasna cloud sync",
3
+ "version": "0.1.10",
4
+ "description": "CLI-only shortlink manager for custom domains, click tracking, Cloudflare setup, and repo-native cloud sync",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -31,7 +31,7 @@
31
31
  "SECURITY.md"
32
32
  ],
33
33
  "scripts": {
34
- "build": "rm -rf dist && bun build src/cli/index.ts --outdir dist/cli --target bun --external @hasna/cloud && bun build src/index.ts --outdir dist --target bun --external @hasna/cloud && bun build src/server.ts --outdir dist --target bun --external @hasna/cloud && bun build src/cloudflare.ts --outdir dist --target bun && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
34
+ "build": "rm -rf dist && bun build src/cli/index.ts --outdir dist/cli --target bun && bun build src/index.ts --outdir dist --target bun && bun build src/server.ts --outdir dist --target bun && bun build src/cloudflare.ts --outdir dist --target bun && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
35
35
  "typecheck": "tsc --noEmit",
36
36
  "test": "bun test",
37
37
  "dev:cli": "bun run src/cli/index.ts",
@@ -66,12 +66,13 @@
66
66
  "author": "Andrei Hasna <andrei@hasna.com>",
67
67
  "license": "Apache-2.0",
68
68
  "dependencies": {
69
- "@hasna/cloud": "^0.1.30",
70
69
  "chalk": "^5.4.1",
71
- "commander": "^13.1.0"
70
+ "commander": "^13.1.0",
71
+ "pg": "^8.13.3"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@types/bun": "^1.2.4",
75
+ "@types/pg": "^8.11.11",
75
76
  "typescript": "^5.7.3"
76
77
  }
77
78
  }