@getstrata/bootstrap 0.2.16 → 0.2.18
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/bootstrap/contracts.d.ts +6 -50
- package/dist/core/contracts/applicationContext.d.ts +7 -18
- package/dist/core/contracts/container.d.ts +30 -0
- package/dist/core/contracts/di.d.ts +31 -0
- package/dist/core/contracts/serviceContainer.d.ts +1 -5
- package/dist/core/runtime/applicationRegistry.d.ts +2 -2
- package/dist/entries/applicationRegistry.js +15 -3
- package/dist/entries/cache/modelCacheTags.js +22 -0
- package/dist/entries/context.js +16 -25
- package/dist/entries/contracts.js +2 -1
- package/dist/entries/http/securedRouteModelBinding.js +15 -3
- package/dist/entries/membershipService.js +15 -3
- package/dist/entries/providers.js +15 -3
- package/dist/entries/queue/defaultJobs.js +15 -3
- package/dist/entries/web/forms.js +53 -0
- package/dist/entries/web/routing.js +636 -0
- package/dist/entries/web/server.js +57 -0
- package/dist/entries/web/session.js +99 -0
- package/dist/entries/web/slug.js +8 -0
- package/dist/framework/public-api.d.ts +3 -2
- package/dist/index.js +17 -25
- package/package.json +33 -3
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../../src/bootstrap/web/session.ts
|
|
3
|
+
import { createHash, randomBytes } from "crypto";
|
|
4
|
+
|
|
5
|
+
// ../../src/core/http/cookies.ts
|
|
6
|
+
function readRequestCookie(request, name) {
|
|
7
|
+
const cookies = request.cookies;
|
|
8
|
+
if (cookies && typeof cookies.get === "function") {
|
|
9
|
+
const value = cookies.get(name);
|
|
10
|
+
if (value) {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const header = request.headers.get("cookie");
|
|
15
|
+
if (!header) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
for (const part of header.split(";")) {
|
|
19
|
+
const idx = part.indexOf("=");
|
|
20
|
+
if (idx === -1)
|
|
21
|
+
continue;
|
|
22
|
+
const cookieName = part.slice(0, idx).trim();
|
|
23
|
+
if (cookieName !== name)
|
|
24
|
+
continue;
|
|
25
|
+
return decodeURIComponent(part.slice(idx + 1).trim());
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ../../src/bootstrap/web/session.ts
|
|
31
|
+
class CookieSessionStore {
|
|
32
|
+
sql;
|
|
33
|
+
secret;
|
|
34
|
+
cookieName;
|
|
35
|
+
maxAgeSeconds;
|
|
36
|
+
constructor(sql, secret, cookieName = "strata_session", maxAgeSeconds = 60 * 60 * 24 * 14) {
|
|
37
|
+
this.sql = sql;
|
|
38
|
+
this.secret = secret;
|
|
39
|
+
this.cookieName = cookieName;
|
|
40
|
+
this.maxAgeSeconds = maxAgeSeconds;
|
|
41
|
+
}
|
|
42
|
+
cookieHeader(_user, sessionId) {
|
|
43
|
+
const payload = `${sessionId}.${this.sign(sessionId)}`;
|
|
44
|
+
return this.withSecureFlag(`${this.cookieName}=${payload}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${this.maxAgeSeconds}`);
|
|
45
|
+
}
|
|
46
|
+
clearCookieHeader() {
|
|
47
|
+
return this.withSecureFlag(`${this.cookieName}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`);
|
|
48
|
+
}
|
|
49
|
+
withSecureFlag(header) {
|
|
50
|
+
if (true) {
|
|
51
|
+
return header;
|
|
52
|
+
}
|
|
53
|
+
return header.includes("Secure") ? header : `${header}; Secure`;
|
|
54
|
+
}
|
|
55
|
+
async create(user) {
|
|
56
|
+
const id = randomBytes(32).toString("hex");
|
|
57
|
+
const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
|
|
58
|
+
await this.sql.unsafe(`INSERT INTO sessions (id, user_id, expires_at) VALUES ($1, $2, $3)`, [
|
|
59
|
+
id,
|
|
60
|
+
user.id,
|
|
61
|
+
expires
|
|
62
|
+
]);
|
|
63
|
+
return id;
|
|
64
|
+
}
|
|
65
|
+
async destroy(sessionId) {
|
|
66
|
+
await this.sql.unsafe(`DELETE FROM sessions WHERE id = $1`, [sessionId]);
|
|
67
|
+
}
|
|
68
|
+
async read(request) {
|
|
69
|
+
const cookie = readRequestCookie(request, this.cookieName);
|
|
70
|
+
const raw = cookie ?? null;
|
|
71
|
+
if (!raw)
|
|
72
|
+
return null;
|
|
73
|
+
const [sessionId, signature] = raw.split(".");
|
|
74
|
+
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const rows = await this.sql.unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
78
|
+
COALESCE(u.is_admin, false) AS is_admin
|
|
79
|
+
FROM sessions s
|
|
80
|
+
INNER JOIN users u ON u.id = s.user_id
|
|
81
|
+
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
82
|
+
const row = rows[0];
|
|
83
|
+
if (!row)
|
|
84
|
+
return null;
|
|
85
|
+
return {
|
|
86
|
+
id: row.user_id,
|
|
87
|
+
name: row.name,
|
|
88
|
+
email: row.email,
|
|
89
|
+
learn_subscriber: row.learn_subscriber,
|
|
90
|
+
is_admin: row.is_admin
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
sign(value) {
|
|
94
|
+
return createHash("sha256").update(`${value}.${this.secret}`).digest("hex").slice(0, 32);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
CookieSessionStore
|
|
99
|
+
};
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* Stable framework surface for application modules and future package extraction.
|
|
3
3
|
* Import from `@getstrata/core` (workspace) or `src/framework/public-api`.
|
|
4
4
|
*/
|
|
5
|
-
export type { ServiceProvider } from "../bootstrap/contracts.ts";
|
|
6
|
-
export { ConfigStore, resolveService, ServiceContainer, } from "../bootstrap/contracts.ts";
|
|
7
5
|
export type { AdminColumn, AdminColumnType, AdminResource, AdminResourceDefinition, AdminResourceHandlers, } from "../core/admin/index.ts";
|
|
8
6
|
export { AdminResourceRegistry, formatAdminValue, } from "../core/admin/index.ts";
|
|
9
7
|
export type { AbilityChecker } from "../core/auth/abilityChecker.ts";
|
|
@@ -21,6 +19,9 @@ export { createScimAuthMiddleware } from "../core/auth/scimAuthMiddleware.ts";
|
|
|
21
19
|
export { type CacheDriver, type CreateCacheStoreOptions, createCacheStore, } from "../core/cache/createCacheStore.ts";
|
|
22
20
|
export { default as CacheRepository } from "../core/cache/repository.ts";
|
|
23
21
|
export { CACHE_TAGS } from "../core/cache/tags.ts";
|
|
22
|
+
export { ConfigStore, ServiceContainer } from "../core/contracts/container.ts";
|
|
23
|
+
export type { ServiceProvider } from "../core/contracts/di.ts";
|
|
24
|
+
export { resolveService } from "../core/contracts/di.ts";
|
|
24
25
|
export type { DatabaseConnection } from "../core/database/baseRepository.ts";
|
|
25
26
|
export { default as BaseRepository } from "../core/database/baseRepository.ts";
|
|
26
27
|
export { bindDatabaseConnection } from "../core/database/bindConnection.ts";
|
package/dist/index.js
CHANGED
|
@@ -503,15 +503,27 @@ async function scheduleRunCommand() {
|
|
|
503
503
|
}
|
|
504
504
|
await runDueScheduledTasks(appSchedule);
|
|
505
505
|
}
|
|
506
|
-
// ../../src/core/contracts/
|
|
506
|
+
// ../../src/core/contracts/di.ts
|
|
507
|
+
var requiredDependencyKeys = [
|
|
508
|
+
"container",
|
|
509
|
+
"cache",
|
|
510
|
+
"storage"
|
|
511
|
+
];
|
|
507
512
|
function getRequiredDependency(dependencies, key) {
|
|
508
513
|
const dependency = dependencies[key];
|
|
509
514
|
if (dependency === undefined) {
|
|
510
|
-
throw new Error(`Required dependency "${
|
|
515
|
+
throw new Error(`Required dependency "${key}" is not registered.`);
|
|
511
516
|
}
|
|
512
517
|
return dependency;
|
|
513
518
|
}
|
|
514
|
-
|
|
519
|
+
function assertAppDependenciesComplete(dependencies) {
|
|
520
|
+
for (const key of requiredDependencyKeys) {
|
|
521
|
+
getRequiredDependency(dependencies, key);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function resolveService(dependencies, token) {
|
|
525
|
+
return dependencies.container.resolve(token);
|
|
526
|
+
}
|
|
515
527
|
// ../../src/core/contracts/serviceTokens.ts
|
|
516
528
|
var CORE_CONFIG_TOKEN = "core.config";
|
|
517
529
|
var CORE_CACHE_TOKEN = "core.cache";
|
|
@@ -595,7 +607,7 @@ var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
|
595
607
|
var DEFAULT_CACHE_DRIVER = "array";
|
|
596
608
|
var DEFAULT_API_TOKEN = "";
|
|
597
609
|
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
598
|
-
// ../../src/
|
|
610
|
+
// ../../src/core/contracts/container.ts
|
|
599
611
|
class ServiceContainer {
|
|
600
612
|
services = new Map;
|
|
601
613
|
singletonFactories = new Map;
|
|
@@ -659,26 +671,6 @@ class ConfigStore {
|
|
|
659
671
|
return this.values.has(key);
|
|
660
672
|
}
|
|
661
673
|
}
|
|
662
|
-
var requiredDependencyKeys = [
|
|
663
|
-
"container",
|
|
664
|
-
"cache",
|
|
665
|
-
"storage"
|
|
666
|
-
];
|
|
667
|
-
function getRequiredDependency2(dependencies, key) {
|
|
668
|
-
const dependency = dependencies[key];
|
|
669
|
-
if (dependency === undefined) {
|
|
670
|
-
throw new Error(`Required dependency "${key}" is not registered.`);
|
|
671
|
-
}
|
|
672
|
-
return dependency;
|
|
673
|
-
}
|
|
674
|
-
function assertAppDependenciesComplete(dependencies) {
|
|
675
|
-
for (const key of requiredDependencyKeys) {
|
|
676
|
-
getRequiredDependency2(dependencies, key);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
function resolveService(dependencies, token) {
|
|
680
|
-
return dependencies.container.resolve(token);
|
|
681
|
-
}
|
|
682
674
|
// ../../src/config/auth.ts
|
|
683
675
|
var authConfig = {
|
|
684
676
|
allowDevHeaders: (process.env.AUTH_DEV_HEADERS ?? "true") !== "false",
|
|
@@ -5291,7 +5283,7 @@ export {
|
|
|
5291
5283
|
prefixRouteMap,
|
|
5292
5284
|
parseFormBody,
|
|
5293
5285
|
mergeWebRoutes,
|
|
5294
|
-
|
|
5286
|
+
getRequiredDependency,
|
|
5295
5287
|
discoverModelTableNames,
|
|
5296
5288
|
createWebServer,
|
|
5297
5289
|
createWebRoutes,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
"import": "./dist/entries/applicationRegistry.js",
|
|
21
21
|
"default": "./dist/entries/applicationRegistry.js"
|
|
22
22
|
},
|
|
23
|
+
"./cache/modelCacheTags": {
|
|
24
|
+
"types": "./dist/bootstrap/cache/modelCacheTags.d.ts",
|
|
25
|
+
"import": "./dist/entries/cache/modelCacheTags.js",
|
|
26
|
+
"default": "./dist/entries/cache/modelCacheTags.js"
|
|
27
|
+
},
|
|
23
28
|
"./config": {
|
|
24
29
|
"types": "./dist/bootstrap/config.d.ts",
|
|
25
30
|
"import": "./dist/entries/config.js",
|
|
@@ -69,6 +74,31 @@
|
|
|
69
74
|
"types": "./dist/bootstrap/providers/view/index.d.ts",
|
|
70
75
|
"import": "./dist/entries/providers/view.js",
|
|
71
76
|
"default": "./dist/entries/providers/view.js"
|
|
77
|
+
},
|
|
78
|
+
"./web/forms": {
|
|
79
|
+
"types": "./dist/bootstrap/web/forms.d.ts",
|
|
80
|
+
"import": "./dist/entries/web/forms.js",
|
|
81
|
+
"default": "./dist/entries/web/forms.js"
|
|
82
|
+
},
|
|
83
|
+
"./web/routing": {
|
|
84
|
+
"types": "./dist/bootstrap/web/routing.d.ts",
|
|
85
|
+
"import": "./dist/entries/web/routing.js",
|
|
86
|
+
"default": "./dist/entries/web/routing.js"
|
|
87
|
+
},
|
|
88
|
+
"./web/server": {
|
|
89
|
+
"types": "./dist/bootstrap/web/server.d.ts",
|
|
90
|
+
"import": "./dist/entries/web/server.js",
|
|
91
|
+
"default": "./dist/entries/web/server.js"
|
|
92
|
+
},
|
|
93
|
+
"./web/session": {
|
|
94
|
+
"types": "./dist/bootstrap/web/session.d.ts",
|
|
95
|
+
"import": "./dist/entries/web/session.js",
|
|
96
|
+
"default": "./dist/entries/web/session.js"
|
|
97
|
+
},
|
|
98
|
+
"./web/slug": {
|
|
99
|
+
"types": "./dist/bootstrap/web/slug.d.ts",
|
|
100
|
+
"import": "./dist/entries/web/slug.js",
|
|
101
|
+
"default": "./dist/entries/web/slug.js"
|
|
72
102
|
}
|
|
73
103
|
},
|
|
74
104
|
"main": "./dist/index.js",
|
|
@@ -82,14 +112,14 @@
|
|
|
82
112
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external @getstrata/core",
|
|
83
113
|
"build:types": "tsc -p tsconfig.types.json",
|
|
84
114
|
"prepublishOnly": "bun run build",
|
|
85
|
-
"build:subpaths": "bun build entries/applicationRegistry.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/membershipService.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core",
|
|
115
|
+
"build:subpaths": "bun build entries/applicationRegistry.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/membershipService.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/web/forms.ts entries/web/routing.ts entries/web/server.ts entries/web/session.ts entries/web/slug.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core",
|
|
86
116
|
"build:shims": "true"
|
|
87
117
|
},
|
|
88
118
|
"publishConfig": {
|
|
89
119
|
"access": "public"
|
|
90
120
|
},
|
|
91
121
|
"peerDependencies": {
|
|
92
|
-
"@getstrata/core": "^0.5.
|
|
122
|
+
"@getstrata/core": "^0.5.26",
|
|
93
123
|
"typescript": "^5.9.0"
|
|
94
124
|
}
|
|
95
125
|
}
|