@hasna/shortlinks 0.1.22 → 0.1.24
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/README.md +40 -20
- package/dist/cli/index.js +2507 -2019
- package/dist/cloudflare.js +141 -4
- package/dist/db/migrations.d.ts +20 -0
- package/dist/generated/storage-kit/health.d.ts +19 -0
- package/dist/generated/storage-kit/index.d.ts +7 -0
- package/dist/generated/storage-kit/migrations.d.ts +47 -0
- package/dist/generated/storage-kit/mode.d.ts +47 -0
- package/dist/generated/storage-kit/pool.d.ts +33 -0
- package/dist/generated/storage-kit/query.d.ts +35 -0
- package/dist/generated/storage-kit/tls.d.ts +25 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3139 -232
- package/dist/mcp/http.d.ts +16 -0
- package/dist/mcp/index.d.ts +14 -0
- package/dist/mcp/index.js +1493 -0
- package/dist/pg-store.d.ts +20 -2
- package/dist/pg-store.js +913 -0
- package/dist/runtime.d.ts +65 -0
- package/dist/runtime.js +214 -0
- package/dist/sdk/generated.d.ts +178 -0
- package/dist/sdk/index.d.ts +12 -0
- package/dist/sdk/index.js +500 -0
- package/dist/serve/app.d.ts +21 -0
- package/dist/serve/index.d.ts +14 -0
- package/dist/serve/index.js +8817 -0
- package/dist/serve/openapi.d.ts +8 -0
- package/dist/server.js +33 -0
- package/infra/aws-ec2-user-data.sh +32 -31
- package/package.json +29 -7
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI 3 description of the shortlinks serve HTTP API.
|
|
3
|
+
*
|
|
4
|
+
* This is the single source of truth for the generated SDK
|
|
5
|
+
* (`@hasna/shortlinks-sdk`) — run `bun run sdk:generate` after changing it —
|
|
6
|
+
* and is also served live at `GET /openapi.json`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildOpenApiDocument(version: string): Record<string, unknown>;
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
12
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
+
for (let key of __getOwnPropNames(mod))
|
|
23
|
+
if (!__hasOwnProp.call(to, key))
|
|
24
|
+
__defProp(to, key, {
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
26
|
+
enumerable: true
|
|
27
|
+
});
|
|
28
|
+
if (canCache)
|
|
29
|
+
cache.set(mod, to);
|
|
30
|
+
return to;
|
|
31
|
+
};
|
|
32
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
+
var __require = import.meta.require;
|
|
34
|
+
|
|
2
35
|
// src/store.ts
|
|
3
36
|
import { createHash } from "crypto";
|
|
4
37
|
|
|
@@ -4,9 +4,7 @@ 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
|
|
8
|
-
export RDS_HOST="hasnaxyz-prod-opensource.c4limg0qgqvk.us-east-1.rds.amazonaws.com"
|
|
9
|
-
export RDS_USERNAME="hasna_admin"
|
|
7
|
+
export SHORTLINKS_DATABASE_SECRET_ID="${SHORTLINKS_DATABASE_SECRET_ID:-hasna/xyz/opensource/shortlinks/prod/postgres}"
|
|
10
8
|
|
|
11
9
|
dnf update -y
|
|
12
10
|
dnf install -y awscli jq tar gzip shadow-utils libcap
|
|
@@ -15,28 +13,14 @@ if ! id shortlinks >/dev/null 2>&1; then
|
|
|
15
13
|
useradd --system --create-home --home-dir "${SHORTLINKS_HOME}" --shell /sbin/nologin shortlinks
|
|
16
14
|
fi
|
|
17
15
|
|
|
18
|
-
install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/cloud"
|
|
19
16
|
install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/shortlinks"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"password_env": "HASNA_RDS_PASSWORD",
|
|
28
|
-
"ssl": true
|
|
29
|
-
},
|
|
30
|
-
"mode": "hybrid",
|
|
31
|
-
"feedback_endpoint": "https://feedback.hasna.com/api/v1/feedback",
|
|
32
|
-
"auto_sync_interval_minutes": 0,
|
|
33
|
-
"sync": {
|
|
34
|
-
"schedule_minutes": 0
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
CLOUD_CONFIG
|
|
38
|
-
chown shortlinks:shortlinks "${SHORTLINKS_HOME}/.hasna/cloud/config.json"
|
|
39
|
-
chmod 600 "${SHORTLINKS_HOME}/.hasna/cloud/config.json"
|
|
17
|
+
cat > /etc/shortlinks.env <<ENV
|
|
18
|
+
SHORTLINKS_DATABASE_SECRET_ID=${SHORTLINKS_DATABASE_SECRET_ID}
|
|
19
|
+
HASNA_SHORTLINKS_STORE=postgres
|
|
20
|
+
HASNA_SHORTLINKS_DATABASE_SSL=true
|
|
21
|
+
ENV
|
|
22
|
+
chown root:shortlinks /etc/shortlinks.env
|
|
23
|
+
chmod 640 /etc/shortlinks.env
|
|
40
24
|
|
|
41
25
|
su -s /bin/bash shortlinks -c 'curl -fsSL https://bun.sh/install | bash'
|
|
42
26
|
su -s /bin/bash shortlinks -c "${SHORTLINKS_HOME}/.bun/bin/bun install -g ${SHORTLINKS_PACKAGE} --no-cache"
|
|
@@ -48,16 +32,32 @@ set -euo pipefail
|
|
|
48
32
|
export AWS_REGION="${AWS_REGION:-us-east-1}"
|
|
49
33
|
export HOME="/var/lib/shortlinks"
|
|
50
34
|
export PATH="/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin"
|
|
51
|
-
export
|
|
35
|
+
export HASNA_SHORTLINKS_STORE="postgres"
|
|
36
|
+
export HASNA_SHORTLINKS_DATABASE_SSL="${HASNA_SHORTLINKS_DATABASE_SSL:-true}"
|
|
52
37
|
|
|
53
38
|
secret_json="$(aws secretsmanager get-secret-value \
|
|
54
39
|
--region "${AWS_REGION}" \
|
|
55
|
-
--secret-id "
|
|
40
|
+
--secret-id "${SHORTLINKS_DATABASE_SECRET_ID:-hasna/xyz/opensource/shortlinks/prod/postgres}" \
|
|
56
41
|
--query SecretString \
|
|
57
42
|
--output text)"
|
|
58
43
|
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
connection_url="$(jq -r '(.connectionString // .connection_string // .url // .database_url // empty)' <<<"${secret_json}")"
|
|
45
|
+
if [[ -z "${connection_url}" ]]; then
|
|
46
|
+
db_host="$(jq -r '.host // empty' <<<"${secret_json}")"
|
|
47
|
+
db_port="$(jq -r '.port // 5432' <<<"${secret_json}")"
|
|
48
|
+
db_name="$(jq -r '.database // .dbname // "shortlinks"' <<<"${secret_json}")"
|
|
49
|
+
db_user="$(jq -r '.username // .user // empty' <<<"${secret_json}")"
|
|
50
|
+
db_password="$(jq -r '.password // empty' <<<"${secret_json}")"
|
|
51
|
+
if [[ -z "${db_host}" || -z "${db_user}" || -z "${db_password}" ]]; then
|
|
52
|
+
echo "Shortlinks database secret must include connectionString/url or host, username, and password." >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
db_user_encoded="$(jq -nr --arg value "${db_user}" '$value|@uri')"
|
|
56
|
+
db_password_encoded="$(jq -nr --arg value "${db_password}" '$value|@uri')"
|
|
57
|
+
connection_url="postgres://${db_user_encoded}:${db_password_encoded}@${db_host}:${db_port}/${db_name}"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
export HASNA_SHORTLINKS_DATABASE_URL="${connection_url}"
|
|
61
61
|
|
|
62
62
|
exec "$@"
|
|
63
63
|
RUNNER
|
|
@@ -90,8 +90,9 @@ Group=shortlinks
|
|
|
90
90
|
WorkingDirectory=/var/lib/shortlinks
|
|
91
91
|
Environment=HOME=/var/lib/shortlinks
|
|
92
92
|
Environment=PATH=/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
EnvironmentFile=/etc/shortlinks.env
|
|
94
|
+
ExecStartPre=/usr/local/bin/shortlinks-env-exec shortlinks postgres migrate
|
|
95
|
+
ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks --store postgres serve --host 127.0.0.1 --port 8787 --default-host has.na
|
|
95
96
|
Restart=always
|
|
96
97
|
RestartSec=5
|
|
97
98
|
|
|
@@ -133,4 +134,4 @@ CADDY
|
|
|
133
134
|
systemctl daemon-reload
|
|
134
135
|
systemctl enable shortlinks.service caddy.service
|
|
135
136
|
systemctl start shortlinks.service
|
|
136
|
-
systemctl start caddy.service
|
|
137
|
+
systemctl start caddy.service
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/shortlinks",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "CLI-only shortlink manager for custom domains, click tracking, Cloudflare setup, and
|
|
3
|
+
"version": "0.1.24",
|
|
4
|
+
"description": "CLI-only shortlink manager for custom domains, click tracking, Cloudflare setup, and app-owned Postgres runtime support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"shortlinks": "dist/cli/index.js"
|
|
9
|
+
"shortlinks": "dist/cli/index.js",
|
|
10
|
+
"shortlinks-mcp": "dist/mcp/index.js",
|
|
11
|
+
"shortlinks-serve": "dist/serve/index.js"
|
|
10
12
|
},
|
|
11
13
|
"exports": {
|
|
12
14
|
".": {
|
|
@@ -20,6 +22,18 @@
|
|
|
20
22
|
"./cloudflare": {
|
|
21
23
|
"types": "./dist/cloudflare.d.ts",
|
|
22
24
|
"import": "./dist/cloudflare.js"
|
|
25
|
+
},
|
|
26
|
+
"./postgres": {
|
|
27
|
+
"types": "./dist/pg-store.d.ts",
|
|
28
|
+
"import": "./dist/pg-store.js"
|
|
29
|
+
},
|
|
30
|
+
"./runtime": {
|
|
31
|
+
"types": "./dist/runtime.d.ts",
|
|
32
|
+
"import": "./dist/runtime.js"
|
|
33
|
+
},
|
|
34
|
+
"./sdk": {
|
|
35
|
+
"types": "./dist/sdk/index.d.ts",
|
|
36
|
+
"import": "./dist/sdk/index.js"
|
|
23
37
|
}
|
|
24
38
|
},
|
|
25
39
|
"files": [
|
|
@@ -31,11 +45,15 @@
|
|
|
31
45
|
"SECURITY.md"
|
|
32
46
|
],
|
|
33
47
|
"scripts": {
|
|
34
|
-
"build": "rm -rf dist && bun build src/cli/index.ts
|
|
48
|
+
"build": "rm -rf dist && bun build src/cli/index.ts src/mcp/index.ts src/serve/index.ts src/sdk/index.ts src/index.ts src/server.ts src/cloudflare.ts src/runtime.ts src/pg-store.ts --root src --outdir dist --target bun --external @modelcontextprotocol/sdk && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
|
|
49
|
+
"sdk:generate": "bun run scripts/generate-sdk.ts",
|
|
35
50
|
"typecheck": "tsc --noEmit",
|
|
36
51
|
"test": "bun test",
|
|
37
52
|
"dev:cli": "bun run src/cli/index.ts",
|
|
38
|
-
"
|
|
53
|
+
"dev:mcp": "bun run src/mcp/index.ts",
|
|
54
|
+
"dev:serve": "bun run src/serve/index.ts",
|
|
55
|
+
"verify:release": "bun run typecheck && bun run test && bun run build",
|
|
56
|
+
"prepublishOnly": "bun run verify:release"
|
|
39
57
|
},
|
|
40
58
|
"keywords": [
|
|
41
59
|
"shortlinks",
|
|
@@ -66,12 +84,16 @@
|
|
|
66
84
|
"author": "Andrei Hasna <andrei@hasna.com>",
|
|
67
85
|
"license": "Apache-2.0",
|
|
68
86
|
"dependencies": {
|
|
69
|
-
"@hasna/
|
|
87
|
+
"@hasna/contracts": "0.4.1",
|
|
70
88
|
"@hasna/events": "^0.1.6",
|
|
89
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
71
90
|
"chalk": "^5.4.1",
|
|
72
|
-
"commander": "^13.1.0"
|
|
91
|
+
"commander": "^13.1.0",
|
|
92
|
+
"hono": "^4.12.7",
|
|
93
|
+
"pg": "^8.13.3"
|
|
73
94
|
},
|
|
74
95
|
"devDependencies": {
|
|
96
|
+
"@types/pg": "^8.11.11",
|
|
75
97
|
"@types/bun": "^1.2.4",
|
|
76
98
|
"typescript": "^5.7.3"
|
|
77
99
|
}
|