@hasna/shortlinks 0.1.11 → 0.1.13
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/LICENSE +152 -191
- package/README.md +21 -18
- package/cloudflare/shortlinks.js +9 -0
- package/cloudflare/wrangler.example.toml +2 -1
- package/dist/cli/index.js +6055 -764
- package/dist/cloudflare.js +10 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5412 -81
- package/dist/pg-migrate.d.ts +7 -0
- package/dist/pg-store.d.ts +2 -1
- package/dist/remote-storage.d.ts +11 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +4 -0
- package/dist/storage-config.d.ts +37 -0
- package/dist/storage-sync.d.ts +36 -0
- package/dist/storage.d.ts +6 -0
- package/dist/storage.js +5539 -0
- package/infra/aws-ec2-user-data.sh +38 -16
- package/package.json +11 -6
package/dist/pg-store.d.ts
CHANGED
|
@@ -9,7 +9,8 @@ export declare class PgShortlinksStore {
|
|
|
9
9
|
private readonly pg;
|
|
10
10
|
constructor(pg: PgAdapterLike);
|
|
11
11
|
static fromConnectionString(connectionString: string): Promise<PgShortlinksStore>;
|
|
12
|
-
static
|
|
12
|
+
static fromStorage(service?: string): Promise<PgShortlinksStore>;
|
|
13
|
+
static fromCloud: typeof PgShortlinksStore.fromStorage;
|
|
13
14
|
close(): Promise<void>;
|
|
14
15
|
addDomain(input: AddDomainInput): Promise<Domain>;
|
|
15
16
|
listDomains(): Promise<Domain[]>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class PgAdapterAsync {
|
|
2
|
+
private readonly pool;
|
|
3
|
+
constructor(connectionString: string);
|
|
4
|
+
run(sql: string, ...params: unknown[]): Promise<{
|
|
5
|
+
changes: number;
|
|
6
|
+
}>;
|
|
7
|
+
get(sql: string, ...params: unknown[]): Promise<unknown>;
|
|
8
|
+
all(sql: string, ...params: unknown[]): Promise<unknown[]>;
|
|
9
|
+
exec(sql: string): Promise<void>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
package/dist/server.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface ShortlinksHandlerOptions {
|
|
|
17
17
|
dbPath?: string;
|
|
18
18
|
defaultHost?: string;
|
|
19
19
|
redirectStatus?: 301 | 302 | 307 | 308;
|
|
20
|
+
reservedPathPrefixes?: string[];
|
|
20
21
|
}
|
|
21
22
|
export declare function createShortlinksHandler(options?: ShortlinksHandlerOptions): (request: Request) => Response | Promise<Response>;
|
|
22
23
|
export declare function serveShortlinks(options?: ShortlinksHandlerOptions & {
|
package/dist/server.js
CHANGED
|
@@ -555,6 +555,7 @@ function isExpired(link) {
|
|
|
555
555
|
function createShortlinksHandler(options = {}) {
|
|
556
556
|
const store = options.store || new ShortlinksStore(options.dbPath);
|
|
557
557
|
const redirectStatus = options.redirectStatus || 302;
|
|
558
|
+
const reservedPathPrefixes = new Set((options.reservedPathPrefixes ?? ["a"]).map((prefix) => prefix.toLowerCase()));
|
|
558
559
|
return async (request) => {
|
|
559
560
|
const url = new URL(request.url);
|
|
560
561
|
if (url.pathname === "/healthz") {
|
|
@@ -571,6 +572,9 @@ function createShortlinksHandler(options = {}) {
|
|
|
571
572
|
}
|
|
572
573
|
if (!slug)
|
|
573
574
|
return json({ error: "Missing slug." }, 404);
|
|
575
|
+
if (reservedPathPrefixes.has(slug.toLowerCase())) {
|
|
576
|
+
return json({ error: "Reserved path prefix.", slug }, 404);
|
|
577
|
+
}
|
|
574
578
|
const host = getHost(request, options.defaultHost);
|
|
575
579
|
if (!host)
|
|
576
580
|
return json({ error: "Missing Host header." }, 400);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type StorageMode = "local" | "remote" | "hybrid";
|
|
2
|
+
export interface StorageConfig {
|
|
3
|
+
mode: StorageMode;
|
|
4
|
+
rds: {
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
username: string;
|
|
8
|
+
password_env: string;
|
|
9
|
+
ssl: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface StorageEnv {
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const SHORTLINKS_STORAGE_ENV = "HASNA_SHORTLINKS_DATABASE_URL";
|
|
16
|
+
export declare const SHORTLINKS_STORAGE_FALLBACK_ENV = "SHORTLINKS_DATABASE_URL";
|
|
17
|
+
export declare const SHORTLINKS_STORAGE_MODE_ENV = "HASNA_SHORTLINKS_STORAGE_MODE";
|
|
18
|
+
export declare const SHORTLINKS_STORAGE_MODE_FALLBACK_ENV = "SHORTLINKS_STORAGE_MODE";
|
|
19
|
+
export declare const STORAGE_DATABASE_ENV: readonly ["HASNA_SHORTLINKS_DATABASE_URL", "SHORTLINKS_DATABASE_URL"];
|
|
20
|
+
export declare const STORAGE_MODE_ENV: readonly ["HASNA_SHORTLINKS_STORAGE_MODE", "SHORTLINKS_STORAGE_MODE"];
|
|
21
|
+
export declare const CANONICAL_SHORTLINKS_RDS_CLUSTER = "postgres-compatible-database";
|
|
22
|
+
export declare const CANONICAL_SHORTLINKS_RDS_DATABASE = "shortlinks";
|
|
23
|
+
export declare const CANONICAL_SHORTLINKS_RDS_SECRET_PATH = "configured-by-environment";
|
|
24
|
+
export interface CanonicalShortlinksRdsConfig {
|
|
25
|
+
cluster: typeof CANONICAL_SHORTLINKS_RDS_CLUSTER;
|
|
26
|
+
database: typeof CANONICAL_SHORTLINKS_RDS_DATABASE;
|
|
27
|
+
runtimeSecretPath: typeof CANONICAL_SHORTLINKS_RDS_SECRET_PATH;
|
|
28
|
+
primaryEnv: typeof SHORTLINKS_STORAGE_ENV;
|
|
29
|
+
fallbackEnv: typeof SHORTLINKS_STORAGE_FALLBACK_ENV;
|
|
30
|
+
}
|
|
31
|
+
export declare function getCanonicalShortlinksRdsConfig(): CanonicalShortlinksRdsConfig;
|
|
32
|
+
export declare function getStorageDatabaseUrl(): string | undefined;
|
|
33
|
+
export declare function getStorageDatabaseEnvName(): (typeof STORAGE_DATABASE_ENV)[number] | null;
|
|
34
|
+
export declare function getStorageDatabaseEnv(): StorageEnv | null;
|
|
35
|
+
export declare function getStorageConfig(): StorageConfig;
|
|
36
|
+
export declare function getStorageConnectionString(dbName?: string): string;
|
|
37
|
+
export declare const getConnectionString: typeof getStorageConnectionString;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { STORAGE_DATABASE_ENV, type CanonicalShortlinksRdsConfig, type StorageMode } from "./storage-config.js";
|
|
2
|
+
import { PgAdapterAsync } from "./remote-storage.js";
|
|
3
|
+
export interface StorageSyncResult {
|
|
4
|
+
table: string;
|
|
5
|
+
direction: "push" | "pull";
|
|
6
|
+
rowsRead: number;
|
|
7
|
+
rowsWritten: number;
|
|
8
|
+
errors: string[];
|
|
9
|
+
}
|
|
10
|
+
export type SyncResult = StorageSyncResult;
|
|
11
|
+
export interface StorageStatus {
|
|
12
|
+
configured: boolean;
|
|
13
|
+
mode: StorageMode;
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
env: typeof STORAGE_DATABASE_ENV;
|
|
16
|
+
activeEnv: string | null;
|
|
17
|
+
canonical: CanonicalShortlinksRdsConfig;
|
|
18
|
+
service: "shortlinks";
|
|
19
|
+
db_path: string;
|
|
20
|
+
tables: Array<{
|
|
21
|
+
table: string;
|
|
22
|
+
rows: number;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export declare const STORAGE_TABLES: readonly ["domains", "links", "clicks"];
|
|
26
|
+
export declare const SHORTLINKS_STORAGE_TABLES: readonly ["domains", "links", "clicks"];
|
|
27
|
+
export declare function getStoragePg(): Promise<PgAdapterAsync>;
|
|
28
|
+
export declare function runStorageMigrations(remote: PgAdapterAsync): Promise<void>;
|
|
29
|
+
export declare function getStorageStatus(dbPath?: string): StorageStatus;
|
|
30
|
+
export declare function pushStorageChanges(dbPath?: string, tables?: string[]): Promise<StorageSyncResult[]>;
|
|
31
|
+
export declare function pullStorageChanges(dbPath?: string, tables?: string[]): Promise<StorageSyncResult[]>;
|
|
32
|
+
export declare function syncStorageChanges(dbPath?: string, tables?: string[]): Promise<{
|
|
33
|
+
push: StorageSyncResult[];
|
|
34
|
+
pull: StorageSyncResult[];
|
|
35
|
+
}>;
|
|
36
|
+
export declare function parseStorageTables(raw?: string): string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { CANONICAL_SHORTLINKS_RDS_CLUSTER, CANONICAL_SHORTLINKS_RDS_DATABASE, CANONICAL_SHORTLINKS_RDS_SECRET_PATH, SHORTLINKS_STORAGE_ENV, SHORTLINKS_STORAGE_FALLBACK_ENV, SHORTLINKS_STORAGE_MODE_ENV, SHORTLINKS_STORAGE_MODE_FALLBACK_ENV, STORAGE_DATABASE_ENV, STORAGE_MODE_ENV, getConnectionString, getCanonicalShortlinksRdsConfig, getStorageConfig, getStorageConnectionString, getStorageDatabaseEnv, getStorageDatabaseEnvName, getStorageDatabaseUrl, } from "./storage-config.js";
|
|
2
|
+
export type { CanonicalShortlinksRdsConfig, StorageConfig, StorageEnv, StorageMode } from "./storage-config.js";
|
|
3
|
+
export { SHORTLINKS_STORAGE_TABLES, STORAGE_TABLES, getStoragePg, getStorageStatus, parseStorageTables, pullStorageChanges, pushStorageChanges, runStorageMigrations, syncStorageChanges, } from "./storage-sync.js";
|
|
4
|
+
export type { StorageStatus, StorageSyncResult, SyncResult } from "./storage-sync.js";
|
|
5
|
+
export { PgAdapterAsync } from "./remote-storage.js";
|
|
6
|
+
export { PG_MIGRATIONS } from "./pg-migrations.js";
|