@package-broker/core 0.2.15
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/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +2 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory-driver.d.ts +15 -0
- package/dist/cache/memory-driver.d.ts.map +1 -0
- package/dist/cache/memory-driver.js +56 -0
- package/dist/cache/memory-driver.js.map +1 -0
- package/dist/db/d1-driver.d.ts +3 -0
- package/dist/db/d1-driver.d.ts.map +1 -0
- package/dist/db/d1-driver.js +7 -0
- package/dist/db/d1-driver.js.map +1 -0
- package/dist/db/index.d.ts +5 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +4 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +696 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +99 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/factory.d.ts +34 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +121 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +7 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/processor.d.ts +49 -0
- package/dist/jobs/processor.d.ts.map +1 -0
- package/dist/jobs/processor.js +118 -0
- package/dist/jobs/processor.js.map +1 -0
- package/dist/middleware/auth.d.ts +52 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +300 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/composer-version.d.ts +7 -0
- package/dist/middleware/composer-version.d.ts.map +1 -0
- package/dist/middleware/composer-version.js +18 -0
- package/dist/middleware/composer-version.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +7 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +45 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/index.d.ts +5 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +6 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/request-id.d.ts +9 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +36 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/ports.d.ts +32 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +4 -0
- package/dist/ports.js.map +1 -0
- package/dist/queue/consumer.d.ts +18 -0
- package/dist/queue/consumer.d.ts.map +1 -0
- package/dist/queue/consumer.js +82 -0
- package/dist/queue/consumer.js.map +1 -0
- package/dist/queue/index.d.ts +2 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +2 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/memory-driver.d.ts +13 -0
- package/dist/queue/memory-driver.d.ts.map +1 -0
- package/dist/queue/memory-driver.js +22 -0
- package/dist/queue/memory-driver.js.map +1 -0
- package/dist/queue/types.d.ts +19 -0
- package/dist/queue/types.d.ts.map +1 -0
- package/dist/queue/types.js +3 -0
- package/dist/queue/types.js.map +1 -0
- package/dist/routes/api/artifacts.d.ts +25 -0
- package/dist/routes/api/artifacts.d.ts.map +1 -0
- package/dist/routes/api/artifacts.js +57 -0
- package/dist/routes/api/artifacts.js.map +1 -0
- package/dist/routes/api/auth.d.ts +50 -0
- package/dist/routes/api/auth.d.ts.map +1 -0
- package/dist/routes/api/auth.js +268 -0
- package/dist/routes/api/auth.js.map +1 -0
- package/dist/routes/api/index.d.ts +9 -0
- package/dist/routes/api/index.d.ts.map +1 -0
- package/dist/routes/api/index.js +10 -0
- package/dist/routes/api/index.js.map +1 -0
- package/dist/routes/api/packages.d.ts +47 -0
- package/dist/routes/api/packages.d.ts.map +1 -0
- package/dist/routes/api/packages.js +671 -0
- package/dist/routes/api/packages.js.map +1 -0
- package/dist/routes/api/repositories.d.ts +56 -0
- package/dist/routes/api/repositories.d.ts.map +1 -0
- package/dist/routes/api/repositories.js +317 -0
- package/dist/routes/api/repositories.js.map +1 -0
- package/dist/routes/api/settings.d.ts +28 -0
- package/dist/routes/api/settings.d.ts.map +1 -0
- package/dist/routes/api/settings.js +81 -0
- package/dist/routes/api/settings.js.map +1 -0
- package/dist/routes/api/stats.d.ts +21 -0
- package/dist/routes/api/stats.d.ts.map +1 -0
- package/dist/routes/api/stats.js +52 -0
- package/dist/routes/api/stats.js.map +1 -0
- package/dist/routes/api/tokens.d.ts +39 -0
- package/dist/routes/api/tokens.d.ts.map +1 -0
- package/dist/routes/api/tokens.js +191 -0
- package/dist/routes/api/tokens.js.map +1 -0
- package/dist/routes/api/users.d.ts +5 -0
- package/dist/routes/api/users.d.ts.map +1 -0
- package/dist/routes/api/users.js +125 -0
- package/dist/routes/api/users.js.map +1 -0
- package/dist/routes/composer.d.ts +133 -0
- package/dist/routes/composer.d.ts.map +1 -0
- package/dist/routes/composer.js +1179 -0
- package/dist/routes/composer.js.map +1 -0
- package/dist/routes/dist.d.ts +32 -0
- package/dist/routes/dist.d.ts.map +1 -0
- package/dist/routes/dist.js +761 -0
- package/dist/routes/dist.js.map +1 -0
- package/dist/routes/health.d.ts +7 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +22 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +6 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/services/EmailService.d.ts +20 -0
- package/dist/services/EmailService.d.ts.map +1 -0
- package/dist/services/EmailService.js +27 -0
- package/dist/services/EmailService.js.map +1 -0
- package/dist/services/UserService.d.ts +27 -0
- package/dist/services/UserService.d.ts.map +1 -0
- package/dist/services/UserService.js +164 -0
- package/dist/services/UserService.js.map +1 -0
- package/dist/storage/driver.d.ts +65 -0
- package/dist/storage/driver.d.ts.map +1 -0
- package/dist/storage/driver.js +59 -0
- package/dist/storage/driver.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/r2-driver.d.ts +16 -0
- package/dist/storage/r2-driver.d.ts.map +1 -0
- package/dist/storage/r2-driver.js +28 -0
- package/dist/storage/r2-driver.js.map +1 -0
- package/dist/storage/s3-driver.d.ts +22 -0
- package/dist/storage/s3-driver.d.ts.map +1 -0
- package/dist/storage/s3-driver.js +66 -0
- package/dist/storage/s3-driver.js.map +1 -0
- package/dist/sync/github-sync.d.ts +15 -0
- package/dist/sync/github-sync.d.ts.map +1 -0
- package/dist/sync/github-sync.js +39 -0
- package/dist/sync/github-sync.js.map +1 -0
- package/dist/sync/index.d.ts +5 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +6 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/repository-sync.d.ts +18 -0
- package/dist/sync/repository-sync.d.ts.map +1 -0
- package/dist/sync/repository-sync.js +214 -0
- package/dist/sync/repository-sync.js.map +1 -0
- package/dist/sync/strategies/composer-repo.d.ts +11 -0
- package/dist/sync/strategies/composer-repo.d.ts.map +1 -0
- package/dist/sync/strategies/composer-repo.js +269 -0
- package/dist/sync/strategies/composer-repo.js.map +1 -0
- package/dist/sync/strategies/github-api.d.ts +6 -0
- package/dist/sync/strategies/github-api.d.ts.map +1 -0
- package/dist/sync/strategies/github-api.js +137 -0
- package/dist/sync/strategies/github-api.js.map +1 -0
- package/dist/sync/strategies/github-packages.d.ts +7 -0
- package/dist/sync/strategies/github-packages.d.ts.map +1 -0
- package/dist/sync/strategies/github-packages.js +66 -0
- package/dist/sync/strategies/github-packages.js.map +1 -0
- package/dist/sync/strategies/index.d.ts +4 -0
- package/dist/sync/strategies/index.d.ts.map +1 -0
- package/dist/sync/strategies/index.js +5 -0
- package/dist/sync/strategies/index.js.map +1 -0
- package/dist/sync/types.d.ts +60 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +3 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/utils/analytics.d.ts +142 -0
- package/dist/utils/analytics.d.ts.map +1 -0
- package/dist/utils/analytics.js +229 -0
- package/dist/utils/analytics.js.map +1 -0
- package/dist/utils/download.d.ts +10 -0
- package/dist/utils/download.d.ts.map +1 -0
- package/dist/utils/download.js +34 -0
- package/dist/utils/download.js.map +1 -0
- package/dist/utils/encryption.d.ts +20 -0
- package/dist/utils/encryption.d.ts.map +1 -0
- package/dist/utils/encryption.js +76 -0
- package/dist/utils/encryption.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +78 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +134 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/upstream-fetch.d.ts +15 -0
- package/dist/utils/upstream-fetch.d.ts.map +1 -0
- package/dist/utils/upstream-fetch.js +108 -0
- package/dist/utils/upstream-fetch.js.map +1 -0
- package/dist/workflows/index.d.ts +3 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +8 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/package-storage.d.ts +47 -0
- package/dist/workflows/package-storage.d.ts.map +1 -0
- package/dist/workflows/package-storage.js +136 -0
- package/dist/workflows/package-storage.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/routes/api/stats.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAIlB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAW3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,CAAyB;IACtD,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAE7B,4BAA4B;IAC5B,MAAM,CAAC,iBAAiB,CAAC,GAAG,MAAM,EAAE;SACjC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAQ,UAAU,EAAE,CAAC;SACxC,IAAI,CAAC,YAAY,CAAC;SAClB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE5C,MAAM,WAAW,GAAG,iBAAiB,EAAE,KAAK,IAAI,CAAC,CAAC;IAElD,8BAA8B;IAC9B,MAAM,CAAC,cAAc,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAQ,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1F,MAAM,cAAc,GAAG,cAAc,EAAE,KAAK,IAAI,CAAC,CAAC;IAElD,yDAAyD;IACzD,MAAM,CAAC,eAAe,CAAC,GAAG,MAAM,EAAE;SAC/B,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAQ,OAAO,SAAS,CAAC,cAAc,GAAG,EAAE,CAAC;SAChE,IAAI,CAAC,SAAS,CAAC,CAAC;IAEnB,MAAM,cAAc,GAAG,eAAe,EAAE,KAAK,IAAI,CAAC,CAAC;IAEnD,OAAO,CAAC,CAAC,IAAI,CAAC;QACZ,YAAY,EAAE,WAAW;QACzB,eAAe,EAAE,cAAc;QAC/B,eAAe,EAAE,cAAc;KAChC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,CAAyB;IAC7D,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAE7B,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;SACxB,MAAM,CAAC;QACN,SAAS,EAAE,SAAS,CAAC,cAAc;QACnC,eAAe,EAAE,SAAS,CAAC,kBAAkB;KAC9C,CAAC;SACD,IAAI,CAAC,SAAS,CAAC;SACf,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,EAChC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAC/B,CACF;SACA,KAAK,CAAC,CAAC,CAAC,CAAC;IAEZ,OAAO,CAAC,CAAC,IAAI,CAAC;QACZ,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,CAAC;QACnC,eAAe,EAAE,QAAQ,EAAE,eAAe,IAAI,IAAI;KACnD,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { DatabasePort } from '../../ports';
|
|
3
|
+
export interface TokensRouteEnv {
|
|
4
|
+
Bindings: {
|
|
5
|
+
DB: D1Database;
|
|
6
|
+
KV?: KVNamespace;
|
|
7
|
+
};
|
|
8
|
+
Variables: {
|
|
9
|
+
database: DatabasePort;
|
|
10
|
+
requestId?: string;
|
|
11
|
+
session?: {
|
|
12
|
+
userId: string;
|
|
13
|
+
email: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* GET /api/tokens
|
|
19
|
+
* List all tokens (without exposing actual tokens)
|
|
20
|
+
*/
|
|
21
|
+
export declare function listTokens(c: Context<TokensRouteEnv>): Promise<Response>;
|
|
22
|
+
/**
|
|
23
|
+
* POST /api/tokens
|
|
24
|
+
* Create a new token
|
|
25
|
+
* Returns the token ONCE - it cannot be retrieved again
|
|
26
|
+
*/
|
|
27
|
+
export declare function createToken(c: Context<TokensRouteEnv>): Promise<Response>;
|
|
28
|
+
/**
|
|
29
|
+
* DELETE /api/tokens/:id
|
|
30
|
+
* Revoke a token
|
|
31
|
+
*/
|
|
32
|
+
export declare function deleteToken(c: Context<TokensRouteEnv>): Promise<Response>;
|
|
33
|
+
/**
|
|
34
|
+
* PATCH /api/tokens/:id
|
|
35
|
+
* Update token description and/or rate_limit_max
|
|
36
|
+
* Permissions cannot be changed after creation
|
|
37
|
+
*/
|
|
38
|
+
export declare function updateToken(c: Context<TokensRouteEnv>): Promise<Response>;
|
|
39
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../src/routes/api/tokens.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAYhD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE;QACR,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,CAAC,EAAE,WAAW,CAAC;KAClB,CAAC;IACF,SAAS,EAAE;QACT,QAAQ,EAAE,YAAY,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC7C,CAAC;CACH;AAiBD;;;GAGG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAe9E;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2D/E;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwB/E;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoE/E"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PACKAGE.broker
|
|
3
|
+
* Copyright (C) 2025 Łukasz Bajsarowicz
|
|
4
|
+
* Licensed under AGPL-3.0
|
|
5
|
+
*/
|
|
6
|
+
import { tokens } from '../../db/schema';
|
|
7
|
+
import { eq } from 'drizzle-orm';
|
|
8
|
+
import { createTokenSchema, updateTokenSchema } from '@package-broker/shared';
|
|
9
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
10
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
11
|
+
import { nanoid, customAlphabet } from 'nanoid';
|
|
12
|
+
import { getAnalytics } from '../../utils/analytics';
|
|
13
|
+
// Generate high-entropy tokens (64 characters, URL-safe)
|
|
14
|
+
const generateToken = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 64);
|
|
15
|
+
/**
|
|
16
|
+
* Hash token using SHA-256
|
|
17
|
+
*/
|
|
18
|
+
function hashToken(token) {
|
|
19
|
+
const hash = sha256(token);
|
|
20
|
+
return bytesToHex(hash);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if KV is available for rate limiting
|
|
24
|
+
*/
|
|
25
|
+
function isKvAvailableForRateLimiting(kv) {
|
|
26
|
+
return kv !== undefined && kv !== null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* GET /api/tokens
|
|
30
|
+
* List all tokens (without exposing actual tokens)
|
|
31
|
+
*/
|
|
32
|
+
export async function listTokens(c) {
|
|
33
|
+
const db = c.get('database');
|
|
34
|
+
const allTokens = await db.select().from(tokens).orderBy(tokens.created_at);
|
|
35
|
+
const tokenList = allTokens.map((token) => ({
|
|
36
|
+
id: token.id,
|
|
37
|
+
description: token.description,
|
|
38
|
+
permissions: token.permissions || 'readonly', // Fallback for existing tokens
|
|
39
|
+
rate_limit_max: token.rate_limit_max,
|
|
40
|
+
created_at: token.created_at,
|
|
41
|
+
expires_at: token.expires_at,
|
|
42
|
+
last_used_at: token.last_used_at,
|
|
43
|
+
}));
|
|
44
|
+
return c.json(tokenList);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* POST /api/tokens
|
|
48
|
+
* Create a new token
|
|
49
|
+
* Returns the token ONCE - it cannot be retrieved again
|
|
50
|
+
*/
|
|
51
|
+
export async function createToken(c) {
|
|
52
|
+
const body = await c.req.json();
|
|
53
|
+
const validated = createTokenSchema.parse(body);
|
|
54
|
+
// Validate: rate limiting requires KV
|
|
55
|
+
if (validated.rate_limit_max !== null &&
|
|
56
|
+
validated.rate_limit_max !== undefined &&
|
|
57
|
+
validated.rate_limit_max > 0) {
|
|
58
|
+
if (!isKvAvailableForRateLimiting(c.env.KV)) {
|
|
59
|
+
return c.json({
|
|
60
|
+
error: 'Bad Request',
|
|
61
|
+
message: 'Rate limiting requires KV namespace to be configured. Please set rate_limit_max to null or 0, or configure KV namespace in your wrangler.toml.'
|
|
62
|
+
}, 400);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const db = c.get('database');
|
|
66
|
+
const tokenId = nanoid();
|
|
67
|
+
const token = generateToken(); // Generate high-entropy token
|
|
68
|
+
const tokenHash = hashToken(token);
|
|
69
|
+
// Use provided rate_limit_max, or default to 1000 only if not explicitly set to null/0
|
|
70
|
+
const rateLimitMax = validated.rate_limit_max !== null && validated.rate_limit_max !== undefined
|
|
71
|
+
? validated.rate_limit_max
|
|
72
|
+
: 1000;
|
|
73
|
+
await db.insert(tokens).values({
|
|
74
|
+
id: tokenId,
|
|
75
|
+
description: validated.description,
|
|
76
|
+
token_hash: tokenHash,
|
|
77
|
+
permissions: validated.permissions || 'readonly',
|
|
78
|
+
rate_limit_max: rateLimitMax,
|
|
79
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
80
|
+
expires_at: validated.expires_at || null,
|
|
81
|
+
});
|
|
82
|
+
// Track token creation
|
|
83
|
+
const analytics = getAnalytics();
|
|
84
|
+
const requestId = c.get('requestId');
|
|
85
|
+
const session = c.get('session');
|
|
86
|
+
analytics.trackTokenCreated({
|
|
87
|
+
requestId,
|
|
88
|
+
tokenId,
|
|
89
|
+
userId: session?.userId,
|
|
90
|
+
});
|
|
91
|
+
// Return token ONCE - it's never stored in plaintext
|
|
92
|
+
return c.json({
|
|
93
|
+
id: tokenId,
|
|
94
|
+
token: token, // Only time token is returned
|
|
95
|
+
description: validated.description,
|
|
96
|
+
permissions: validated.permissions || 'readonly',
|
|
97
|
+
rate_limit_max: rateLimitMax,
|
|
98
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
99
|
+
expires_at: validated.expires_at || null,
|
|
100
|
+
}, 201);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* DELETE /api/tokens/:id
|
|
104
|
+
* Revoke a token
|
|
105
|
+
*/
|
|
106
|
+
export async function deleteToken(c) {
|
|
107
|
+
const id = c.req.param('id');
|
|
108
|
+
const db = c.get('database');
|
|
109
|
+
// Check if exists
|
|
110
|
+
const [token] = await db.select().from(tokens).where(eq(tokens.id, id)).limit(1);
|
|
111
|
+
if (!token) {
|
|
112
|
+
return c.json({ error: 'Not Found', message: 'Token not found' }, 404);
|
|
113
|
+
}
|
|
114
|
+
await db.delete(tokens).where(eq(tokens.id, id));
|
|
115
|
+
// Track token revocation
|
|
116
|
+
const analytics = getAnalytics();
|
|
117
|
+
const requestId = c.get('requestId');
|
|
118
|
+
const session = c.get('session');
|
|
119
|
+
analytics.trackTokenDeleted({
|
|
120
|
+
requestId,
|
|
121
|
+
tokenId: id,
|
|
122
|
+
userId: session?.userId,
|
|
123
|
+
});
|
|
124
|
+
return c.json({ message: 'Token revoked' });
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* PATCH /api/tokens/:id
|
|
128
|
+
* Update token description and/or rate_limit_max
|
|
129
|
+
* Permissions cannot be changed after creation
|
|
130
|
+
*/
|
|
131
|
+
export async function updateToken(c) {
|
|
132
|
+
const id = c.req.param('id');
|
|
133
|
+
const body = await c.req.json();
|
|
134
|
+
const validated = updateTokenSchema.parse(body);
|
|
135
|
+
// Validate: rate limiting requires KV
|
|
136
|
+
if (validated.rate_limit_max !== null &&
|
|
137
|
+
validated.rate_limit_max !== undefined &&
|
|
138
|
+
validated.rate_limit_max > 0) {
|
|
139
|
+
if (!isKvAvailableForRateLimiting(c.env.KV)) {
|
|
140
|
+
return c.json({
|
|
141
|
+
error: 'Bad Request',
|
|
142
|
+
message: 'Rate limiting requires KV namespace to be configured. Please set rate_limit_max to null or 0, or configure KV namespace in your wrangler.toml.'
|
|
143
|
+
}, 400);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const db = c.get('database');
|
|
147
|
+
// Check if token exists
|
|
148
|
+
const [token] = await db.select().from(tokens).where(eq(tokens.id, id)).limit(1);
|
|
149
|
+
if (!token) {
|
|
150
|
+
return c.json({ error: 'Not Found', message: 'Token not found' }, 404);
|
|
151
|
+
}
|
|
152
|
+
// Build update object - only update provided fields
|
|
153
|
+
const updateData = {};
|
|
154
|
+
if (validated.description !== undefined) {
|
|
155
|
+
updateData.description = validated.description;
|
|
156
|
+
}
|
|
157
|
+
if (validated.rate_limit_max !== undefined) {
|
|
158
|
+
// Allow null/0 to disable rate limiting
|
|
159
|
+
updateData.rate_limit_max = validated.rate_limit_max;
|
|
160
|
+
}
|
|
161
|
+
// Only update if there are fields to update
|
|
162
|
+
if (Object.keys(updateData).length > 0) {
|
|
163
|
+
await db
|
|
164
|
+
.update(tokens)
|
|
165
|
+
.set(updateData)
|
|
166
|
+
.where(eq(tokens.id, id));
|
|
167
|
+
}
|
|
168
|
+
// Fetch updated token
|
|
169
|
+
const [updatedToken] = await db.select().from(tokens).where(eq(tokens.id, id)).limit(1);
|
|
170
|
+
// Track token update (if analytics method exists)
|
|
171
|
+
const analytics = getAnalytics();
|
|
172
|
+
const requestId = c.get('requestId');
|
|
173
|
+
const session = c.get('session');
|
|
174
|
+
if (typeof analytics.trackTokenUpdated === 'function') {
|
|
175
|
+
analytics.trackTokenUpdated({
|
|
176
|
+
requestId,
|
|
177
|
+
tokenId: id,
|
|
178
|
+
userId: session?.userId,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return c.json({
|
|
182
|
+
id: updatedToken.id,
|
|
183
|
+
description: updatedToken.description,
|
|
184
|
+
permissions: updatedToken.permissions || 'readonly',
|
|
185
|
+
rate_limit_max: updatedToken.rate_limit_max,
|
|
186
|
+
created_at: updatedToken.created_at,
|
|
187
|
+
expires_at: updatedToken.expires_at,
|
|
188
|
+
last_used_at: updatedToken.last_used_at,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../../src/routes/api/tokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
export declare function listUsers(c: Context): Promise<Response>;
|
|
3
|
+
export declare function createUser(c: Context): Promise<Response>;
|
|
4
|
+
export declare function deleteUser(c: Context): Promise<Response>;
|
|
5
|
+
//# sourceMappingURL=users.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/routes/api/users.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,wBAAsB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAY7D;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuG9D;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkB9D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { UserService } from '../../services/UserService';
|
|
2
|
+
export async function listUsers(c) {
|
|
3
|
+
const db = c.get('database');
|
|
4
|
+
const userService = new UserService(db);
|
|
5
|
+
// Check permissions (must be admin)
|
|
6
|
+
const session = c.get('session');
|
|
7
|
+
if (session.role !== 'admin') {
|
|
8
|
+
return c.json({ error: 'Forbidden' }, 403);
|
|
9
|
+
}
|
|
10
|
+
const users = await userService.list();
|
|
11
|
+
return c.json({ users });
|
|
12
|
+
}
|
|
13
|
+
export async function createUser(c) {
|
|
14
|
+
const db = c.get('database');
|
|
15
|
+
const userService = new UserService(db);
|
|
16
|
+
// Check permissions
|
|
17
|
+
const session = c.get('session');
|
|
18
|
+
if (session.role !== 'admin') {
|
|
19
|
+
return c.json({ error: 'Forbidden' }, 403);
|
|
20
|
+
}
|
|
21
|
+
let body;
|
|
22
|
+
try {
|
|
23
|
+
body = await c.req.json();
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return c.json({ error: 'Invalid JSON' }, 400);
|
|
27
|
+
}
|
|
28
|
+
const { email, password, role } = body;
|
|
29
|
+
// Password is now optional for invites
|
|
30
|
+
if (!email) {
|
|
31
|
+
return c.json({ error: 'Email is required' }, 400);
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const user = await userService.create({
|
|
35
|
+
email,
|
|
36
|
+
password,
|
|
37
|
+
role: role || 'viewer',
|
|
38
|
+
});
|
|
39
|
+
// Send invite email if SMTP is configured
|
|
40
|
+
if (c.env.SMTP_HOST && c.env.SMTP_USER && c.env.SMTP_PASS) {
|
|
41
|
+
try {
|
|
42
|
+
const { EmailService } = await import('../../services/EmailService');
|
|
43
|
+
const emailService = new EmailService({
|
|
44
|
+
host: c.env.SMTP_HOST,
|
|
45
|
+
port: parseInt(c.env.SMTP_PORT || '587'),
|
|
46
|
+
user: c.env.SMTP_USER,
|
|
47
|
+
pass: c.env.SMTP_PASS,
|
|
48
|
+
from: c.env.SMTP_FROM || c.env.SMTP_USER,
|
|
49
|
+
});
|
|
50
|
+
let subject = 'Welcome to Composer Proxy';
|
|
51
|
+
let text = '';
|
|
52
|
+
let html = '';
|
|
53
|
+
if (user?.invite_token) {
|
|
54
|
+
// Invite Flow
|
|
55
|
+
const origin = c.req.header('origin') || new URL(c.req.url).origin;
|
|
56
|
+
const inviteLink = `${origin}/invite/${user.invite_token}`;
|
|
57
|
+
text = `You have been invited to the Composer Proxy.\n\nPlease accept the invitation and set your password here:\n${inviteLink}`;
|
|
58
|
+
html = `
|
|
59
|
+
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; color: #334155;">
|
|
60
|
+
<h2 style="color: #0f172a;">Welcome to Composer Proxy</h2>
|
|
61
|
+
<p>You have been invited to join the Composer Proxy.</p>
|
|
62
|
+
<p>Please click the button below to accept the invitation and set your password:</p>
|
|
63
|
+
<p style="margin: 24px 0;">
|
|
64
|
+
<a href="${inviteLink}" style="background-color: #f97316; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block; font-weight: bold;">Accept Invitation</a>
|
|
65
|
+
</p>
|
|
66
|
+
<p style="font-size: 0.9em; color: #64748b;">Or copy this link to your browser: <br> ${inviteLink}</p>
|
|
67
|
+
<p style="font-size: 0.8em; color: #94a3b8; margin-top: 40px; border-top: 1px solid #e2e8f0; padding-top: 20px;">
|
|
68
|
+
This invite expires in 7 days.
|
|
69
|
+
</p>
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
else if (password) {
|
|
74
|
+
// Legacy/Manual Password Flow (if admin provided password)
|
|
75
|
+
text = `You have been invited to the Composer Proxy.\n\nYour temporary password is: ${password}\n\nPlease log in and change your password immediately.`;
|
|
76
|
+
html = `
|
|
77
|
+
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; color: #334155;">
|
|
78
|
+
<h2>Welcome to Composer Proxy</h2>
|
|
79
|
+
<p>You have been invited to the Composer Proxy.</p>
|
|
80
|
+
<p>Your temporary password is: <strong>${password}</strong></p>
|
|
81
|
+
<p>Please log in and change your password immediately.</p>
|
|
82
|
+
</div>
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
if (text && html) {
|
|
86
|
+
await emailService.send({ to: email, subject, text, html });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (emailError) {
|
|
90
|
+
console.error('Failed to send invite email:', emailError);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return c.json({
|
|
94
|
+
message: 'User created',
|
|
95
|
+
user: {
|
|
96
|
+
id: user?.id,
|
|
97
|
+
email: user?.email,
|
|
98
|
+
role: user?.role
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (error.message === 'User already exists') {
|
|
104
|
+
return c.json({ error: 'User already exists' }, 409);
|
|
105
|
+
}
|
|
106
|
+
return c.json({ error: 'Failed to create user' }, 500);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export async function deleteUser(c) {
|
|
110
|
+
const db = c.get('database');
|
|
111
|
+
const userService = new UserService(db);
|
|
112
|
+
const userId = c.req.param('id');
|
|
113
|
+
// Check permissions
|
|
114
|
+
const session = c.get('session');
|
|
115
|
+
if (session.role !== 'admin') {
|
|
116
|
+
return c.json({ error: 'Forbidden' }, 403);
|
|
117
|
+
}
|
|
118
|
+
// Prevent self-deletion
|
|
119
|
+
if (session.userId === userId) {
|
|
120
|
+
return c.json({ error: 'Cannot delete own account' }, 400);
|
|
121
|
+
}
|
|
122
|
+
await userService.delete(userId);
|
|
123
|
+
return c.json({ message: 'User deleted' });
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=users.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../../src/routes/api/users.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { DatabasePort } from '../ports';
|
|
3
|
+
import { packages } from '../db/schema';
|
|
4
|
+
import type { StorageDriver } from '../storage/driver';
|
|
5
|
+
export interface ComposerRouteEnv {
|
|
6
|
+
Bindings: {
|
|
7
|
+
DB: D1Database;
|
|
8
|
+
KV?: KVNamespace;
|
|
9
|
+
QUEUE?: Queue;
|
|
10
|
+
PACKAGE_STORAGE_WORKFLOW?: Workflow;
|
|
11
|
+
ENCRYPTION_KEY: string;
|
|
12
|
+
};
|
|
13
|
+
Variables: {
|
|
14
|
+
storage: StorageDriver;
|
|
15
|
+
database: DatabasePort;
|
|
16
|
+
requestId?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* GET /packages.json
|
|
21
|
+
* Serve aggregated packages.json for all private repositories
|
|
22
|
+
* Uses KV caching with stale-while-revalidate strategy
|
|
23
|
+
*/
|
|
24
|
+
export declare function packagesJsonRoute(c: Context<ComposerRouteEnv>): Promise<Response>;
|
|
25
|
+
/**
|
|
26
|
+
* GET /p2/:vendor/:package.json
|
|
27
|
+
* Serve individual package metadata (Composer 2 provider format)
|
|
28
|
+
* Supports public Packagist mirroring with lazy loading
|
|
29
|
+
*/
|
|
30
|
+
export declare function p2PackageRoute(c: Context<ComposerRouteEnv>): Promise<Response>;
|
|
31
|
+
/**
|
|
32
|
+
* Build Composer 2 provider response for a single package from stored metadata
|
|
33
|
+
* Generates clean response with proper types from D1 stored data
|
|
34
|
+
*
|
|
35
|
+
* NOTE: Composer 2 (p2) format expects versions as an ARRAY, not a dict keyed by version.
|
|
36
|
+
* See: https://packagist.org/apidoc
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildP2Response(packageName: string, packageVersions: Array<typeof packages.$inferSelect>): ComposerP2Response;
|
|
39
|
+
/**
|
|
40
|
+
* Ensure Packagist repository exists in database
|
|
41
|
+
* Creates it if it doesn't exist
|
|
42
|
+
*/
|
|
43
|
+
export declare function ensurePackagistRepository(db: DatabasePort, encryptionKey: string, kv?: KVNamespace): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Transform package dist URLs to proxy URLs and store in database
|
|
46
|
+
* Waits for all database writes to complete before returning
|
|
47
|
+
* Returns transformed data along with storage success metrics
|
|
48
|
+
*/
|
|
49
|
+
export declare function transformPackageDistUrls(packageData: any, repoId: string, proxyBaseUrl: string, db: DatabasePort): Promise<{
|
|
50
|
+
transformed: any;
|
|
51
|
+
storedCount: number;
|
|
52
|
+
errors: string[];
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Store package metadata in database (synchronous)
|
|
56
|
+
*/
|
|
57
|
+
export declare function storeLazyPackageMetadata(db: DatabasePort, repoId: string, packageName: string, packageData: any, proxyBaseUrl: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Store a single package in database
|
|
60
|
+
* Throws errors for caller to handle
|
|
61
|
+
*/
|
|
62
|
+
export declare function storePackageInDB(db: DatabasePort, packageName: string, version: string, metadata: any, repoId: string, proxyDistUrl: string, sourceDistUrl: string | null): Promise<void>;
|
|
63
|
+
interface ComposerP2Response {
|
|
64
|
+
packages: Record<string, PackageVersion[]>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Package version metadata in Composer p2 format
|
|
68
|
+
*
|
|
69
|
+
* Required fields:
|
|
70
|
+
* - name: Package name (vendor/package) - MUST be present
|
|
71
|
+
* - version: Version string - MUST be present
|
|
72
|
+
* - dist: Distribution information - MUST be present with at least type and url
|
|
73
|
+
*
|
|
74
|
+
* Optional fields:
|
|
75
|
+
* - time: Release timestamp (ISO 8601)
|
|
76
|
+
* - description: Package description
|
|
77
|
+
* - license: License identifier(s)
|
|
78
|
+
* - type: Package type (e.g., "library", "metapackage")
|
|
79
|
+
* - homepage: Homepage URL
|
|
80
|
+
* - source: Source repository information
|
|
81
|
+
* - require: Runtime dependencies
|
|
82
|
+
* - require-dev: Development dependencies
|
|
83
|
+
* - autoload: Autoload configuration
|
|
84
|
+
* - notification-url: Notification URL
|
|
85
|
+
*/
|
|
86
|
+
interface PackageVersion {
|
|
87
|
+
/** Required: Package name in vendor/package format */
|
|
88
|
+
name: string;
|
|
89
|
+
/** Required: Version string */
|
|
90
|
+
version: string;
|
|
91
|
+
/** Required: Distribution information */
|
|
92
|
+
dist: {
|
|
93
|
+
/** Required: Distribution type (usually "zip") */
|
|
94
|
+
type: string;
|
|
95
|
+
/** Required: Download URL */
|
|
96
|
+
url: string;
|
|
97
|
+
/** Optional: Reference (commit hash, tag, etc.) for mirror URL substitution */
|
|
98
|
+
reference?: string;
|
|
99
|
+
/** Optional: SHA-1 checksum */
|
|
100
|
+
shasum?: string;
|
|
101
|
+
/** Optional: Mirror URLs (used by repository-level mirrors) */
|
|
102
|
+
mirrors?: Array<{
|
|
103
|
+
url: string;
|
|
104
|
+
preferred?: boolean;
|
|
105
|
+
}>;
|
|
106
|
+
};
|
|
107
|
+
/** Optional: Release timestamp */
|
|
108
|
+
time?: string;
|
|
109
|
+
/** Optional: Package description */
|
|
110
|
+
description?: string;
|
|
111
|
+
/** Optional: License identifier(s) */
|
|
112
|
+
license?: string | string[];
|
|
113
|
+
/** Optional: Package type */
|
|
114
|
+
type?: string;
|
|
115
|
+
/** Optional: Homepage URL */
|
|
116
|
+
homepage?: string;
|
|
117
|
+
/** Optional: Source repository information */
|
|
118
|
+
source?: {
|
|
119
|
+
type: string;
|
|
120
|
+
url: string;
|
|
121
|
+
reference: string;
|
|
122
|
+
};
|
|
123
|
+
/** Optional: Runtime dependencies */
|
|
124
|
+
require?: Record<string, string>;
|
|
125
|
+
/** Optional: Development dependencies */
|
|
126
|
+
'require-dev'?: Record<string, string>;
|
|
127
|
+
/** Optional: Autoload configuration */
|
|
128
|
+
autoload?: object;
|
|
129
|
+
/** Optional: Notification URL */
|
|
130
|
+
'notification-url'?: string | null;
|
|
131
|
+
}
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=composer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../src/routes/composer.ts"],"names":[],"mappings":"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"}
|