@hasna/shortlinks 0.2.5 → 0.2.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.
- package/README.md +56 -24
- package/cloudflare/wrangler.example.toml +1 -1
- package/dist/cli/index.js +2009 -6378
- package/dist/cli/projection.d.ts +32 -0
- package/dist/client-store.d.ts +7 -7
- package/dist/cloud-store.d.ts +9 -7
- package/dist/generated/storage-kit/backend.d.ts +19 -0
- package/dist/generated/storage-kit/index.d.ts +2 -2
- package/dist/generated/storage-kit/own.d.ts +10 -0
- package/dist/generated/storage-kit/pool.d.ts +7 -6
- package/dist/generated/storage-kit/tls.d.ts +30 -3
- package/dist/index.js +1117 -6331
- package/dist/mcp/http.d.ts +2 -2
- package/dist/mcp/index.js +588 -6095
- package/dist/sdk/generated.d.ts +4 -4
- package/dist/sdk/index.d.ts +1 -2
- package/dist/sdk/index.js +13 -5
- package/dist/serve/app.d.ts +8 -5
- package/dist/serve/index.d.ts +5 -4
- package/dist/serve/index.js +762 -5251
- package/dist/store-interface.d.ts +4 -2
- package/infra/aws-ec2-user-data.sh +6 -6
- package/package.json +8 -5
- package/dist/generated/storage-kit/mode.d.ts +0 -47
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { AddDomainInput, Click, ClickInput, CreateLinkInput, Domain, Link, LinkStats } from "./types.js";
|
|
2
|
+
/** Plain env shape consumed by the store resolver (own-property reads only). */
|
|
3
|
+
export type Env = Record<string, string | undefined>;
|
|
2
4
|
export interface ListLinksOptions {
|
|
3
5
|
domain?: string;
|
|
4
6
|
activeOnly?: boolean;
|
|
@@ -11,11 +13,11 @@ export interface TotalStats {
|
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* The single storage surface shared by LocalStore and ApiStore. All methods are
|
|
14
|
-
* async so one call site works against either transport
|
|
16
|
+
* async so one call site works against either transport.
|
|
15
17
|
*/
|
|
16
18
|
export interface Store {
|
|
17
19
|
/** Which transport backs this store (for banners/diagnostics only). */
|
|
18
|
-
readonly kind: "local" | "
|
|
20
|
+
readonly kind: "local" | "http";
|
|
19
21
|
addDomain(input: AddDomainInput): Promise<Domain>;
|
|
20
22
|
listDomains(): Promise<Domain[]>;
|
|
21
23
|
getDomain(hostnameOrId: string): Promise<Domain | null>;
|
|
@@ -14,10 +14,13 @@ if ! id shortlinks >/dev/null 2>&1; then
|
|
|
14
14
|
fi
|
|
15
15
|
|
|
16
16
|
install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/shortlinks"
|
|
17
|
+
# The server data backend is selected by HASNA_SHORTLINKS_DATABASE_URL (exported
|
|
18
|
+
# by shortlinks-env-exec below); unset selects the on-box SQLite store. The
|
|
19
|
+
# sanctioned PostgreSQL service entrypoint is `shortlinks-serve` (see
|
|
20
|
+
# Dockerfile) — this unit runs the client-side redirect server, which resolves
|
|
21
|
+
# its store from the client env contract (on-box SQLite or the hosted /v1 API).
|
|
17
22
|
cat > /etc/shortlinks.env <<ENV
|
|
18
23
|
SHORTLINKS_DATABASE_SECRET_ID=${SHORTLINKS_DATABASE_SECRET_ID}
|
|
19
|
-
HASNA_SHORTLINKS_STORE=postgres
|
|
20
|
-
HASNA_SHORTLINKS_DATABASE_SSL=true
|
|
21
24
|
ENV
|
|
22
25
|
chown root:shortlinks /etc/shortlinks.env
|
|
23
26
|
chmod 640 /etc/shortlinks.env
|
|
@@ -32,8 +35,6 @@ set -euo pipefail
|
|
|
32
35
|
export AWS_REGION="${AWS_REGION:-us-east-1}"
|
|
33
36
|
export HOME="/var/lib/shortlinks"
|
|
34
37
|
export PATH="/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin"
|
|
35
|
-
export HASNA_SHORTLINKS_STORE="postgres"
|
|
36
|
-
export HASNA_SHORTLINKS_DATABASE_SSL="${HASNA_SHORTLINKS_DATABASE_SSL:-true}"
|
|
37
38
|
|
|
38
39
|
secret_json="$(aws secretsmanager get-secret-value \
|
|
39
40
|
--region "${AWS_REGION}" \
|
|
@@ -91,8 +92,7 @@ WorkingDirectory=/var/lib/shortlinks
|
|
|
91
92
|
Environment=HOME=/var/lib/shortlinks
|
|
92
93
|
Environment=PATH=/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin
|
|
93
94
|
EnvironmentFile=/etc/shortlinks.env
|
|
94
|
-
|
|
95
|
-
ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks --store postgres serve --host 127.0.0.1 --port 8787 --default-host has.na
|
|
95
|
+
ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks serve --host 127.0.0.1 --port 8787 --default-host has.na
|
|
96
96
|
Restart=always
|
|
97
97
|
RestartSec=5
|
|
98
98
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/shortlinks",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Shortlink manager for custom domains and click tracking, with local SQLite or
|
|
3
|
+
"version": "0.2.10",
|
|
4
|
+
"description": "Shortlink manager for custom domains and click tracking, with local SQLite or hosted /v1 API (bearer key) storage and Cloudflare setup helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -41,15 +41,18 @@
|
|
|
41
41
|
"SECURITY.md"
|
|
42
42
|
],
|
|
43
43
|
"scripts": {
|
|
44
|
-
"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/pg-store.ts --root src --outdir dist --target bun --external @modelcontextprotocol/sdk && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
|
|
44
|
+
"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/pg-store.ts --root src --outdir dist --target bun --external @modelcontextprotocol/sdk --external pg && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
|
|
45
45
|
"sdk:generate": "bun run scripts/generate-sdk.ts",
|
|
46
46
|
"typecheck": "tsc --noEmit",
|
|
47
47
|
"test": "bun test",
|
|
48
|
+
"test:pg": "bun scripts/pg-test-gate.ts",
|
|
49
|
+
"scan:artifact": "bun scripts/scan-artifact.ts",
|
|
48
50
|
"dev:cli": "bun run src/cli/index.ts",
|
|
49
51
|
"dev:mcp": "bun run src/mcp/index.ts",
|
|
50
52
|
"dev:serve": "bun run src/serve/index.ts",
|
|
51
53
|
"verify:release": "bun run typecheck && bun run test && bun run build",
|
|
52
|
-
"prepublishOnly": "bun run verify:release"
|
|
54
|
+
"prepublishOnly": "bun run verify:release",
|
|
55
|
+
"prepack": "bun run build && bun run scan:artifact"
|
|
53
56
|
},
|
|
54
57
|
"keywords": [
|
|
55
58
|
"shortlinks",
|
|
@@ -88,7 +91,7 @@
|
|
|
88
91
|
"pg": "^8.13.3"
|
|
89
92
|
},
|
|
90
93
|
"devDependencies": {
|
|
91
|
-
"@hasna/contracts": "
|
|
94
|
+
"@hasna/contracts": "0.13.1",
|
|
92
95
|
"@types/pg": "^8.11.11",
|
|
93
96
|
"@types/bun": "^1.2.4",
|
|
94
97
|
"typescript": "^5.7.3"
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export declare const STORAGE_MODES: readonly ["local", "cloud"];
|
|
2
|
-
export type StorageMode = (typeof STORAGE_MODES)[number];
|
|
3
|
-
export declare const DEPRECATED_STORAGE_MODE_ALIASES: readonly ["remote", "hybrid", "self_hosted"];
|
|
4
|
-
export type Env = Record<string, string | undefined>;
|
|
5
|
-
export interface StorageModeNormalization {
|
|
6
|
-
mode: StorageMode;
|
|
7
|
-
/** The deprecated alias that was normalized to `cloud`, if any. */
|
|
8
|
-
deprecatedAlias: string | null;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Normalize a raw storage-mode string to the `local | cloud` runtime enum.
|
|
12
|
-
* Accepts deprecated aliases (`remote`, `hybrid`, `self_hosted`) and maps them
|
|
13
|
-
* to `cloud`. Throws on any other value.
|
|
14
|
-
*/
|
|
15
|
-
export declare function normalizeStorageMode(value: string): StorageModeNormalization;
|
|
16
|
-
/** Upper-snake env token for an app name, e.g. `todos` -> `TODOS`. */
|
|
17
|
-
export declare function envToken(name: string): string;
|
|
18
|
-
export interface StorageEnvKeys {
|
|
19
|
-
/** `HASNA_<NAME>_STORAGE_MODE` then the optional `<NAME>_STORAGE_MODE` alias. */
|
|
20
|
-
modeKeys: string[];
|
|
21
|
-
/** `HASNA_<NAME>_DATABASE_URL` then the optional `<NAME>_DATABASE_URL` alias. */
|
|
22
|
-
databaseUrlKeys: string[];
|
|
23
|
-
}
|
|
24
|
-
/** Resolve the canonical env-key spec for an app's storage config. */
|
|
25
|
-
export declare function storageEnvKeys(name: string): StorageEnvKeys;
|
|
26
|
-
export interface StorageModeResolution {
|
|
27
|
-
mode: StorageMode;
|
|
28
|
-
/** Env key the mode came from, or `"default"`. */
|
|
29
|
-
source: string;
|
|
30
|
-
deprecatedAlias: string | null;
|
|
31
|
-
databaseUrlPresent: boolean;
|
|
32
|
-
/** Env key the database URL came from, or `null`. */
|
|
33
|
-
databaseUrlSource: string | null;
|
|
34
|
-
warning: string | null;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Resolve an app's storage mode from the environment per the contract env spec.
|
|
38
|
-
* Precedence: `HASNA_<NAME>_STORAGE_MODE`, then `<NAME>_STORAGE_MODE`, else
|
|
39
|
-
* `local`. Never reads secret values — only detects DATABASE_URL presence.
|
|
40
|
-
*/
|
|
41
|
-
export declare function resolveStorageMode(name: string, env?: Env): StorageModeResolution;
|
|
42
|
-
/**
|
|
43
|
-
* Resolve the database URL value for an app, honoring the canonical then alias
|
|
44
|
-
* env keys. Returns `null` when unset. The caller is responsible for never
|
|
45
|
-
* logging the returned value.
|
|
46
|
-
*/
|
|
47
|
-
export declare function resolveDatabaseUrl(name: string, env?: Env): string | null;
|