@getstrata/bootstrap 0.2.50 → 0.2.52
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/CHANGELOG.md +11 -0
- package/README.md +1 -1
- package/dist/bootstrap/public-api.d.ts +1 -1
- package/dist/bootstrap/web/index.d.ts +1 -1
- package/dist/bootstrap/web/routing.d.ts +7 -1
- package/dist/bootstrap/web/session.d.ts +19 -2
- package/dist/entries/context.js +16 -2
- package/dist/entries/createRoutes.js +4 -4
- package/dist/entries/createWebRoutes.js +2 -2
- package/dist/entries/dependencies.js +16 -2
- package/dist/entries/providers/view.js +16 -2
- package/dist/entries/providers.js +16 -2
- package/dist/entries/web/server.js +31 -14
- package/dist/entries/web/session.js +73 -25
- package/dist/index.js +122 -43
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @getstrata/bootstrap changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.52
|
|
4
|
+
|
|
5
|
+
- View provider registers `configureWebErrorView` so `errors/*.eta` render through the app Eta layout. `EtaViewEngine` receives `Request` from the layout-data resolver.
|
|
6
|
+
- `createWebServer` unknown routes and null handlers return styled HTML 404s and run inside request ALS so `configureWebLayoutData` can read the session cookie.
|
|
7
|
+
- `wrapSecuredRouteModelByKey` is documented as the wrong default for public HTML show pages; a missing model is a styled 404 and HTML/composite GET ETags stay off.
|
|
8
|
+
|
|
9
|
+
## 0.2.51
|
|
10
|
+
|
|
11
|
+
- `createCookieSessionAuthManager` returns `CookieSessionAuthManager` (`signIn`, `signOut`, `signInRedirect`, `signOutRedirect`). Controllers no longer need a local cookie helper.
|
|
12
|
+
- Pass `loadSessionUser` to replace the default `users.learn_subscriber` / `users.is_admin` session query. Keep `mapUser` in the app.
|
|
13
|
+
|
|
3
14
|
## 0.2.50
|
|
4
15
|
|
|
5
16
|
- `createCookieSessionAuthManager` / `CookieSessionGuard` turn `CookieSessionStore` into an `AuthGuard` / `AuthManager` for `CORE_AUTH_TOKEN`. Supply a `mapUser` mapper; WorkHub abilities are not baked in. Omit `sql` to read the client from `bindDatabaseConnection()` on every call.
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ import { createHttpKernel, createAppContext, coreProviders } from "@getstrata/bo
|
|
|
30
30
|
|
|
31
31
|
`createAppContext()` does not call `assertProductionSecrets`. WorkHub calls that from `App.serve()` / `queue:work`. Sibling HTMX apps can call it in production without WorkHub API tokens when feature flags are off — see [SIBLING-HTMX.md](../../docs/SIBLING-HTMX.md).
|
|
32
32
|
|
|
33
|
-
Sibling HTMX apps should bind `createCookieSessionAuthManager` from `@getstrata/bootstrap/web/session` instead of HMAC `SessionGuard`. `
|
|
33
|
+
Sibling HTMX apps should bind `createCookieSessionAuthManager` from `@getstrata/bootstrap/web/session` instead of HMAC `SessionGuard`. Use `signIn` / `signOut` (or the redirect helpers) instead of calling `CookieSessionStore` from controllers. Pass `mapUser` to map roles in the app. Pass `loadSessionUser` when the default `learn_subscriber` / `is_admin` SELECT does not match your schema.
|
|
34
34
|
|
|
35
35
|
`wrapWeb` applies the web group (CSRF + flash) and `withErrorHandling`, so CSRF `ForbiddenError` becomes an HTML 403 in `FRONTEND_MODE=server-htmx`. `wrapWebLogin` / `wrapWebRegister` include that web group plus throttle — do not wrap them with `wrapWeb` again.
|
|
36
36
|
|
|
@@ -27,4 +27,4 @@ export { coreProviders } from "./providers/index.ts";
|
|
|
27
27
|
export { registerDefaultJobs } from "./queue/defaultJobs.ts";
|
|
28
28
|
export { RouteRegistry, routeRegistry } from "./routeRegistry.ts";
|
|
29
29
|
export { assertProductionSecrets } from "./secretsGuard.ts";
|
|
30
|
-
export { CookieSessionGuard, CookieSessionStore, createCookieSessionAuthManager, createCsrfProtection, createRouteKernel, createWebServer, type MapSessionUser, type ParsedForm, parseFormBody, routeParams, type SessionUser, slugify, toRouteRequest, type WebServerOptions, wrapSecuredRouteModelByKey, wrapWebLogin, wrapWebRegister, } from "./web/index.ts";
|
|
30
|
+
export { CookieSessionAuthManager, CookieSessionGuard, CookieSessionStore, createCookieSessionAuthManager, createCsrfProtection, createRouteKernel, createWebServer, type LoadSessionUser, type MapSessionUser, type ParsedForm, parseFormBody, routeParams, type SessionUser, slugify, toRouteRequest, type WebServerOptions, wrapSecuredRouteModelByKey, wrapWebLogin, wrapWebRegister, } from "./web/index.ts";
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
export { createCsrfProtection, type ParsedForm, parseFormBody } from "./forms.ts";
|
|
5
5
|
export { createRouteKernel, routeParams, toRouteRequest, wrapSecuredRouteModelByKey, wrapWebLogin, wrapWebRegister, } from "./routing.ts";
|
|
6
6
|
export { convertAppRoutesToBunRoutes, createWebServer, type WebServerOptions } from "./server.ts";
|
|
7
|
-
export { CookieSessionGuard, CookieSessionStore, createCookieSessionAuthManager, type MapSessionUser, type SessionUser, } from "./session.ts";
|
|
7
|
+
export { CookieSessionAuthManager, CookieSessionGuard, CookieSessionStore, createCookieSessionAuthManager, type LoadSessionUser, type MapSessionUser, type SessionUser, } from "./session.ts";
|
|
8
8
|
export { slugify } from "./slug.ts";
|
|
@@ -9,10 +9,16 @@ export declare function routeParams(request: Request): Record<string, string>;
|
|
|
9
9
|
* Mutates the request in place so instanceof Request and Bun internals stay valid.
|
|
10
10
|
*/
|
|
11
11
|
export declare function toRouteRequest<TParams extends Record<string, string>>(request: Request): RouteRequest<TParams>;
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Laravel-style secured route-model binding for string keys (slugs, UUIDs).
|
|
14
|
+
* Public HTML show pages should look up the model in the controller instead.
|
|
15
|
+
* If this wrapper is still used on HTML, a missing model becomes a styled 404
|
|
16
|
+
* and GET ETags are skipped for HTML / composite objects unless `etag: true`.
|
|
17
|
+
*/
|
|
13
18
|
export declare function wrapSecuredRouteModelByKey<TParams extends Record<string, string>, TModel, TParam extends keyof TParams & string>(param: TParam, resolver: (key: string, request: RouteRequest<TParams>) => Promise<TModel>, authorization: {
|
|
14
19
|
resource: string;
|
|
15
20
|
action: "view" | "create" | "update" | "delete";
|
|
21
|
+
etag?: boolean;
|
|
16
22
|
}, handler: (request: RouteRequest<TParams>, model: TModel) => Response | Promise<Response>): RouteHandler;
|
|
17
23
|
/** Web group (CSRF + flash + HTML errors) plus login throttle. Do not wrap with wrapWeb again. */
|
|
18
24
|
export declare function wrapWebLogin(kernel: HttpKernel, handler: RouteHandler, onThrottled: (request: Request) => Response | Promise<Response>): RouteHandler;
|
|
@@ -11,6 +11,7 @@ type SqlClient = {
|
|
|
11
11
|
unsafe<T>(query: string, params?: readonly unknown[]): Promise<T[]>;
|
|
12
12
|
};
|
|
13
13
|
type SqlSource = SqlClient | (() => SqlClient);
|
|
14
|
+
export type LoadSessionUser = (sql: SqlClient, sessionId: string) => Promise<SessionUser | null>;
|
|
14
15
|
declare function defaultSessionSql(): SqlClient;
|
|
15
16
|
export type MapSessionUser = (user: SessionUser) => AuthUser;
|
|
16
17
|
declare function defaultMapSessionUser(user: SessionUser): AuthUser;
|
|
@@ -19,9 +20,11 @@ export declare class CookieSessionStore {
|
|
|
19
20
|
private readonly secret;
|
|
20
21
|
private readonly cookieName;
|
|
21
22
|
private readonly maxAgeSeconds;
|
|
22
|
-
|
|
23
|
+
private readonly loadSessionUser;
|
|
24
|
+
constructor(sqlSource: SqlSource, secret: string, cookieName?: string, maxAgeSeconds?: number, loadSessionUser?: LoadSessionUser);
|
|
23
25
|
cookieHeader(_user: SessionUser, sessionId: string): string;
|
|
24
26
|
clearCookieHeader(): string;
|
|
27
|
+
sessionIdFromRequest(request: Request): string | null;
|
|
25
28
|
private withSecureFlag;
|
|
26
29
|
private sql;
|
|
27
30
|
create(user: SessionUser): Promise<string>;
|
|
@@ -35,6 +38,19 @@ export declare class CookieSessionGuard implements AuthGuard {
|
|
|
35
38
|
constructor(store: CookieSessionStore, mapUser?: MapSessionUser);
|
|
36
39
|
resolve(request: Request): Promise<AuthUser | null>;
|
|
37
40
|
}
|
|
41
|
+
export declare class CookieSessionAuthManager extends AuthManager {
|
|
42
|
+
readonly store: CookieSessionStore;
|
|
43
|
+
constructor(store: CookieSessionStore, mapUser?: MapSessionUser);
|
|
44
|
+
signIn(user: SessionUser): Promise<{
|
|
45
|
+
sessionId: string;
|
|
46
|
+
setCookie: string;
|
|
47
|
+
}>;
|
|
48
|
+
signOut(request: Request): Promise<{
|
|
49
|
+
setCookie: string;
|
|
50
|
+
}>;
|
|
51
|
+
signInRedirect(user: SessionUser, location: string, status?: number): Promise<Response>;
|
|
52
|
+
signOutRedirect(request: Request, location: string, status?: number): Promise<Response>;
|
|
53
|
+
}
|
|
38
54
|
export interface CreateCookieSessionAuthManagerOptions {
|
|
39
55
|
store?: CookieSessionStore;
|
|
40
56
|
sql?: SqlSource;
|
|
@@ -42,6 +58,7 @@ export interface CreateCookieSessionAuthManagerOptions {
|
|
|
42
58
|
cookieName?: string;
|
|
43
59
|
maxAgeSeconds?: number;
|
|
44
60
|
mapUser?: MapSessionUser;
|
|
61
|
+
loadSessionUser?: LoadSessionUser;
|
|
45
62
|
}
|
|
46
|
-
declare function createCookieSessionAuthManager(options?: CreateCookieSessionAuthManagerOptions):
|
|
63
|
+
declare function createCookieSessionAuthManager(options?: CreateCookieSessionAuthManagerOptions): CookieSessionAuthManager;
|
|
47
64
|
export { createCookieSessionAuthManager, defaultMapSessionUser, defaultSessionSql };
|
package/dist/entries/context.js
CHANGED
|
@@ -460,7 +460,13 @@ var storage_default = storageProvider;
|
|
|
460
460
|
|
|
461
461
|
// ../../src/bootstrap/providers/view.ts
|
|
462
462
|
import { currentRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
463
|
-
import {
|
|
463
|
+
import {
|
|
464
|
+
configureWebErrorView,
|
|
465
|
+
DEFAULT_VIEWS_DIRECTORY,
|
|
466
|
+
EtaViewEngine,
|
|
467
|
+
errorTemplateName,
|
|
468
|
+
resolveWebLayoutData
|
|
469
|
+
} from "@getstrata/core/view";
|
|
464
470
|
|
|
465
471
|
// ../../src/config/frontend.ts
|
|
466
472
|
function readFrontendMode() {
|
|
@@ -491,7 +497,15 @@ var viewProvider = {
|
|
|
491
497
|
}
|
|
492
498
|
const viewsDirectory = process.env.VIEW_DIRECTORY?.trim() || DEFAULT_VIEWS_DIRECTORY;
|
|
493
499
|
config.set(VIEW_DIRECTORY_CONFIG_KEY, viewsDirectory);
|
|
494
|
-
|
|
500
|
+
const engine = new EtaViewEngine(viewsDirectory, (request) => resolveWebLayoutData(container, request ?? currentRequestMeta().request));
|
|
501
|
+
container.set(CORE_VIEW_TOKEN, engine);
|
|
502
|
+
configureWebErrorView({
|
|
503
|
+
render: async (input) => engine.render(errorTemplateName(input.status), {
|
|
504
|
+
title: input.title,
|
|
505
|
+
message: input.message,
|
|
506
|
+
errors: input.errors
|
|
507
|
+
})
|
|
508
|
+
});
|
|
495
509
|
}
|
|
496
510
|
};
|
|
497
511
|
|
|
@@ -4,7 +4,7 @@ var __jsonParse = (a) => JSON.parse(a);
|
|
|
4
4
|
// ../../src/bootstrap/createRoutes.ts
|
|
5
5
|
import { applyMiddlewareToRoutes as applyMiddlewareToRoutes3 } from "@getstrata/core/http/middleware";
|
|
6
6
|
import { jsonResponse as jsonResponse4 } from "@getstrata/core/http/response";
|
|
7
|
-
import {
|
|
7
|
+
import { notFoundHtmlResponse as notFoundHtmlResponse2 } from "@getstrata/core/view";
|
|
8
8
|
|
|
9
9
|
// ../../index.html
|
|
10
10
|
var strata_default = __jsonParse("{\"index\":\"_.._/_.._/index.html\",\"files\":[{\"input\":\"../../index.html\",\"path\":\"./index-sfreg6q3.js\",\"loader\":\"js\",\"isEntry\":true,\"headers\":{\"etag\":\"Oc_YLpCmV6M\",\"content-type\":\"text/javascript;charset=utf-8\"}},{\"input\":\"../../index.html\",\"path\":\"_.._/_.._/index.html\",\"loader\":\"html\",\"isEntry\":true,\"headers\":{\"etag\":\"rWY90LWIcx8\",\"content-type\":\"text/html;charset=utf-8\"}}]}");
|
|
@@ -508,7 +508,7 @@ function mergeSpaRoutes(dependencies, routes) {
|
|
|
508
508
|
|
|
509
509
|
// ../../src/bootstrap/createWebRoutes.ts
|
|
510
510
|
import { join as join3 } from "path";
|
|
511
|
-
import {
|
|
511
|
+
import { notFoundHtmlResponse } from "@getstrata/core/view";
|
|
512
512
|
|
|
513
513
|
// ../../src/bootstrap/buildWebModuleRoutes.ts
|
|
514
514
|
import { applyMiddlewareToRoutes as applyMiddlewareToRoutes2 } from "@getstrata/core/http/middleware";
|
|
@@ -551,7 +551,7 @@ function createWebRoutes(dependencies) {
|
|
|
551
551
|
const relativePath = pathname.replace(/^\//, "");
|
|
552
552
|
const file = Bun.file(join3(process.cwd(), "public", relativePath));
|
|
553
553
|
if (!await file.exists()) {
|
|
554
|
-
return
|
|
554
|
+
return notFoundHtmlResponse();
|
|
555
555
|
}
|
|
556
556
|
return new Response(file);
|
|
557
557
|
};
|
|
@@ -1428,7 +1428,7 @@ function createRoutes(dependencies) {
|
|
|
1428
1428
|
"/*": async () => {
|
|
1429
1429
|
registerRoute2("GET", "/*", []);
|
|
1430
1430
|
if (isViewsEnabled()) {
|
|
1431
|
-
return
|
|
1431
|
+
return notFoundHtmlResponse2();
|
|
1432
1432
|
}
|
|
1433
1433
|
if (isSpaEnabled()) {
|
|
1434
1434
|
return jsonResponse4({ error: "Not Found" }, { status: 404 });
|
|
@@ -3,7 +3,7 @@ var __jsonParse = (a) => JSON.parse(a);
|
|
|
3
3
|
|
|
4
4
|
// ../../src/bootstrap/createWebRoutes.ts
|
|
5
5
|
import { join as join2 } from "path";
|
|
6
|
-
import {
|
|
6
|
+
import { notFoundHtmlResponse } from "@getstrata/core/view";
|
|
7
7
|
|
|
8
8
|
// ../../src/config/frontend.ts
|
|
9
9
|
function readFrontendMode() {
|
|
@@ -478,7 +478,7 @@ function createWebRoutes(dependencies) {
|
|
|
478
478
|
const relativePath = pathname.replace(/^\//, "");
|
|
479
479
|
const file = Bun.file(join2(process.cwd(), "public", relativePath));
|
|
480
480
|
if (!await file.exists()) {
|
|
481
|
-
return
|
|
481
|
+
return notFoundHtmlResponse();
|
|
482
482
|
}
|
|
483
483
|
return new Response(file);
|
|
484
484
|
};
|
|
@@ -460,7 +460,13 @@ var storage_default = storageProvider;
|
|
|
460
460
|
|
|
461
461
|
// ../../src/bootstrap/providers/view.ts
|
|
462
462
|
import { currentRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
463
|
-
import {
|
|
463
|
+
import {
|
|
464
|
+
configureWebErrorView,
|
|
465
|
+
DEFAULT_VIEWS_DIRECTORY,
|
|
466
|
+
EtaViewEngine,
|
|
467
|
+
errorTemplateName,
|
|
468
|
+
resolveWebLayoutData
|
|
469
|
+
} from "@getstrata/core/view";
|
|
464
470
|
|
|
465
471
|
// ../../src/config/frontend.ts
|
|
466
472
|
function readFrontendMode() {
|
|
@@ -491,7 +497,15 @@ var viewProvider = {
|
|
|
491
497
|
}
|
|
492
498
|
const viewsDirectory = process.env.VIEW_DIRECTORY?.trim() || DEFAULT_VIEWS_DIRECTORY;
|
|
493
499
|
config.set(VIEW_DIRECTORY_CONFIG_KEY, viewsDirectory);
|
|
494
|
-
|
|
500
|
+
const engine = new EtaViewEngine(viewsDirectory, (request) => resolveWebLayoutData(container, request ?? currentRequestMeta().request));
|
|
501
|
+
container.set(CORE_VIEW_TOKEN, engine);
|
|
502
|
+
configureWebErrorView({
|
|
503
|
+
render: async (input) => engine.render(errorTemplateName(input.status), {
|
|
504
|
+
title: input.title,
|
|
505
|
+
message: input.message,
|
|
506
|
+
errors: input.errors
|
|
507
|
+
})
|
|
508
|
+
});
|
|
495
509
|
}
|
|
496
510
|
};
|
|
497
511
|
|
|
@@ -3,7 +3,13 @@ var __jsonParse = (a) => JSON.parse(a);
|
|
|
3
3
|
|
|
4
4
|
// ../../src/bootstrap/providers/view.ts
|
|
5
5
|
import { currentRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
configureWebErrorView,
|
|
8
|
+
DEFAULT_VIEWS_DIRECTORY,
|
|
9
|
+
EtaViewEngine,
|
|
10
|
+
errorTemplateName,
|
|
11
|
+
resolveWebLayoutData
|
|
12
|
+
} from "@getstrata/core/view";
|
|
7
13
|
|
|
8
14
|
// ../../src/config/frontend.ts
|
|
9
15
|
function readFrontendMode() {
|
|
@@ -34,7 +40,15 @@ var viewProvider = {
|
|
|
34
40
|
}
|
|
35
41
|
const viewsDirectory = process.env.VIEW_DIRECTORY?.trim() || DEFAULT_VIEWS_DIRECTORY;
|
|
36
42
|
config.set(VIEW_DIRECTORY_CONFIG_KEY, viewsDirectory);
|
|
37
|
-
|
|
43
|
+
const engine = new EtaViewEngine(viewsDirectory, (request) => resolveWebLayoutData(container, request ?? currentRequestMeta().request));
|
|
44
|
+
container.set(CORE_VIEW_TOKEN, engine);
|
|
45
|
+
configureWebErrorView({
|
|
46
|
+
render: async (input) => engine.render(errorTemplateName(input.status), {
|
|
47
|
+
title: input.title,
|
|
48
|
+
message: input.message,
|
|
49
|
+
errors: input.errors
|
|
50
|
+
})
|
|
51
|
+
});
|
|
38
52
|
}
|
|
39
53
|
};
|
|
40
54
|
export {
|
|
@@ -450,7 +450,13 @@ var storage_default = storageProvider;
|
|
|
450
450
|
|
|
451
451
|
// ../../src/bootstrap/providers/view.ts
|
|
452
452
|
import { currentRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
453
|
-
import {
|
|
453
|
+
import {
|
|
454
|
+
configureWebErrorView,
|
|
455
|
+
DEFAULT_VIEWS_DIRECTORY,
|
|
456
|
+
EtaViewEngine,
|
|
457
|
+
errorTemplateName,
|
|
458
|
+
resolveWebLayoutData
|
|
459
|
+
} from "@getstrata/core/view";
|
|
454
460
|
|
|
455
461
|
// ../../src/config/frontend.ts
|
|
456
462
|
function readFrontendMode() {
|
|
@@ -481,7 +487,15 @@ var viewProvider = {
|
|
|
481
487
|
}
|
|
482
488
|
const viewsDirectory = process.env.VIEW_DIRECTORY?.trim() || DEFAULT_VIEWS_DIRECTORY;
|
|
483
489
|
config.set(VIEW_DIRECTORY_CONFIG_KEY, viewsDirectory);
|
|
484
|
-
|
|
490
|
+
const engine = new EtaViewEngine(viewsDirectory, (request) => resolveWebLayoutData(container, request ?? currentRequestMeta().request));
|
|
491
|
+
container.set(CORE_VIEW_TOKEN, engine);
|
|
492
|
+
configureWebErrorView({
|
|
493
|
+
render: async (input) => engine.render(errorTemplateName(input.status), {
|
|
494
|
+
title: input.title,
|
|
495
|
+
message: input.message,
|
|
496
|
+
errors: input.errors
|
|
497
|
+
})
|
|
498
|
+
});
|
|
485
499
|
}
|
|
486
500
|
};
|
|
487
501
|
|
|
@@ -2,10 +2,21 @@
|
|
|
2
2
|
var __jsonParse = (a) => JSON.parse(a);
|
|
3
3
|
|
|
4
4
|
// ../../src/bootstrap/web/server.ts
|
|
5
|
+
import { currentRequestMeta, runWithRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
6
|
+
import { notFoundHtmlResponse } from "@getstrata/core/view";
|
|
7
|
+
async function missingHtmlResponse() {
|
|
8
|
+
return notFoundHtmlResponse();
|
|
9
|
+
}
|
|
5
10
|
function wrapRouteHandler(handler) {
|
|
6
11
|
return async (request) => {
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
return await runWithRequestMeta({
|
|
13
|
+
...currentRequestMeta(),
|
|
14
|
+
request,
|
|
15
|
+
userAgent: request.headers.get("user-agent")
|
|
16
|
+
}, async () => {
|
|
17
|
+
const response = await handler(request);
|
|
18
|
+
return response ?? await missingHtmlResponse();
|
|
19
|
+
});
|
|
9
20
|
};
|
|
10
21
|
}
|
|
11
22
|
function convertAppRoutesToBunRoutes(routes) {
|
|
@@ -37,19 +48,25 @@ function createWebServer(options) {
|
|
|
37
48
|
port: options.port,
|
|
38
49
|
...bunRoutes ? { routes: bunRoutes } : {},
|
|
39
50
|
async fetch(request) {
|
|
40
|
-
await
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
return await runWithRequestMeta({
|
|
52
|
+
...currentRequestMeta(),
|
|
53
|
+
request,
|
|
54
|
+
userAgent: request.headers.get("user-agent")
|
|
55
|
+
}, async () => {
|
|
56
|
+
await options.onRequest?.(request);
|
|
57
|
+
const url = new URL(request.url);
|
|
58
|
+
if (url.pathname.startsWith("/assets/")) {
|
|
59
|
+
const file = Bun.file(`${publicDir}${url.pathname}`);
|
|
60
|
+
if (await file.exists()) {
|
|
61
|
+
return new Response(file);
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
64
|
+
if (options.handle) {
|
|
65
|
+
const response = await options.handle(request);
|
|
66
|
+
return response ?? await missingHtmlResponse();
|
|
67
|
+
}
|
|
68
|
+
return await missingHtmlResponse();
|
|
69
|
+
});
|
|
53
70
|
}
|
|
54
71
|
});
|
|
55
72
|
}
|
|
@@ -29,17 +29,45 @@ function defaultMapSessionUser(user) {
|
|
|
29
29
|
role: user.is_admin ? "admin" : "member"
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
async function defaultLoadSessionUser(sql, sessionId) {
|
|
33
|
+
const rows = await sql.unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
34
|
+
COALESCE(u.is_admin, false) AS is_admin
|
|
35
|
+
FROM sessions s
|
|
36
|
+
INNER JOIN users u ON u.id = s.user_id
|
|
37
|
+
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
38
|
+
const row = rows[0];
|
|
39
|
+
if (!row)
|
|
40
|
+
return null;
|
|
41
|
+
return {
|
|
42
|
+
id: row.user_id,
|
|
43
|
+
name: row.name,
|
|
44
|
+
email: row.email,
|
|
45
|
+
learn_subscriber: row.learn_subscriber,
|
|
46
|
+
is_admin: row.is_admin
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function redirectWithCookie(location, setCookie, status) {
|
|
50
|
+
return new Response(null, {
|
|
51
|
+
status,
|
|
52
|
+
headers: {
|
|
53
|
+
Location: location,
|
|
54
|
+
"Set-Cookie": setCookie
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
32
58
|
|
|
33
59
|
class CookieSessionStore {
|
|
34
60
|
sqlSource;
|
|
35
61
|
secret;
|
|
36
62
|
cookieName;
|
|
37
63
|
maxAgeSeconds;
|
|
38
|
-
|
|
64
|
+
loadSessionUser;
|
|
65
|
+
constructor(sqlSource, secret, cookieName = "strata_session", maxAgeSeconds = 60 * 60 * 24 * 14, loadSessionUser = defaultLoadSessionUser) {
|
|
39
66
|
this.sqlSource = sqlSource;
|
|
40
67
|
this.secret = secret;
|
|
41
68
|
this.cookieName = cookieName;
|
|
42
69
|
this.maxAgeSeconds = maxAgeSeconds;
|
|
70
|
+
this.loadSessionUser = loadSessionUser;
|
|
43
71
|
}
|
|
44
72
|
cookieHeader(_user, sessionId) {
|
|
45
73
|
const payload = `${sessionId}.${this.sign(sessionId)}`;
|
|
@@ -48,6 +76,17 @@ class CookieSessionStore {
|
|
|
48
76
|
clearCookieHeader() {
|
|
49
77
|
return this.withSecureFlag(`${this.cookieName}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`);
|
|
50
78
|
}
|
|
79
|
+
sessionIdFromRequest(request) {
|
|
80
|
+
const cookie = readRequestCookie(request, this.cookieName);
|
|
81
|
+
const raw = cookie ?? null;
|
|
82
|
+
if (!raw)
|
|
83
|
+
return null;
|
|
84
|
+
const [sessionId, signature] = raw.split(".");
|
|
85
|
+
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return sessionId;
|
|
89
|
+
}
|
|
51
90
|
withSecureFlag(header) {
|
|
52
91
|
if (true) {
|
|
53
92
|
return header;
|
|
@@ -71,29 +110,10 @@ class CookieSessionStore {
|
|
|
71
110
|
await this.sql().unsafe(`DELETE FROM sessions WHERE id = $1`, [sessionId]);
|
|
72
111
|
}
|
|
73
112
|
async read(request) {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
if (!raw)
|
|
113
|
+
const sessionId = this.sessionIdFromRequest(request);
|
|
114
|
+
if (!sessionId)
|
|
77
115
|
return null;
|
|
78
|
-
|
|
79
|
-
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
const rows = await this.sql().unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
83
|
-
COALESCE(u.is_admin, false) AS is_admin
|
|
84
|
-
FROM sessions s
|
|
85
|
-
INNER JOIN users u ON u.id = s.user_id
|
|
86
|
-
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
87
|
-
const row = rows[0];
|
|
88
|
-
if (!row)
|
|
89
|
-
return null;
|
|
90
|
-
return {
|
|
91
|
-
id: row.user_id,
|
|
92
|
-
name: row.name,
|
|
93
|
-
email: row.email,
|
|
94
|
-
learn_subscriber: row.learn_subscriber,
|
|
95
|
-
is_admin: row.is_admin
|
|
96
|
-
};
|
|
116
|
+
return this.loadSessionUser(this.sql(), sessionId);
|
|
97
117
|
}
|
|
98
118
|
sign(value) {
|
|
99
119
|
return createHash("sha256").update(`${value}.${this.secret}`).digest("hex").slice(0, 32);
|
|
@@ -115,11 +135,39 @@ class CookieSessionGuard {
|
|
|
115
135
|
return this.mapUser(user);
|
|
116
136
|
}
|
|
117
137
|
}
|
|
138
|
+
|
|
139
|
+
class CookieSessionAuthManager extends AuthManager {
|
|
140
|
+
store;
|
|
141
|
+
constructor(store, mapUser = defaultMapSessionUser) {
|
|
142
|
+
super(new CookieSessionGuard(store, mapUser));
|
|
143
|
+
this.store = store;
|
|
144
|
+
}
|
|
145
|
+
async signIn(user) {
|
|
146
|
+
const sessionId = await this.store.create(user);
|
|
147
|
+
return { sessionId, setCookie: this.store.cookieHeader(user, sessionId) };
|
|
148
|
+
}
|
|
149
|
+
async signOut(request) {
|
|
150
|
+
const sessionId = this.store.sessionIdFromRequest(request);
|
|
151
|
+
if (sessionId) {
|
|
152
|
+
await this.store.destroy(sessionId);
|
|
153
|
+
}
|
|
154
|
+
return { setCookie: this.store.clearCookieHeader() };
|
|
155
|
+
}
|
|
156
|
+
async signInRedirect(user, location, status = 302) {
|
|
157
|
+
const { setCookie } = await this.signIn(user);
|
|
158
|
+
return redirectWithCookie(location, setCookie, status);
|
|
159
|
+
}
|
|
160
|
+
async signOutRedirect(request, location, status = 302) {
|
|
161
|
+
const { setCookie } = await this.signOut(request);
|
|
162
|
+
return redirectWithCookie(location, setCookie, status);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
118
165
|
function createCookieSessionAuthManager(options = {}) {
|
|
119
|
-
const store = options.store ?? new CookieSessionStore(options.sql ?? defaultSessionSql, options.secret ?? process.env.SESSION_SECRET?.trim() ?? "", options.cookieName, options.maxAgeSeconds);
|
|
120
|
-
return new
|
|
166
|
+
const store = options.store ?? new CookieSessionStore(options.sql ?? defaultSessionSql, options.secret ?? process.env.SESSION_SECRET?.trim() ?? "", options.cookieName, options.maxAgeSeconds, options.loadSessionUser);
|
|
167
|
+
return new CookieSessionAuthManager(store, options.mapUser ?? defaultMapSessionUser);
|
|
121
168
|
}
|
|
122
169
|
export {
|
|
170
|
+
CookieSessionAuthManager,
|
|
123
171
|
CookieSessionGuard,
|
|
124
172
|
CookieSessionStore,
|
|
125
173
|
createCookieSessionAuthManager,
|
package/dist/index.js
CHANGED
|
@@ -806,7 +806,13 @@ var storage_default = storageProvider;
|
|
|
806
806
|
|
|
807
807
|
// ../../src/bootstrap/providers/view.ts
|
|
808
808
|
import { currentRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
809
|
-
import {
|
|
809
|
+
import {
|
|
810
|
+
configureWebErrorView,
|
|
811
|
+
DEFAULT_VIEWS_DIRECTORY,
|
|
812
|
+
EtaViewEngine,
|
|
813
|
+
errorTemplateName,
|
|
814
|
+
resolveWebLayoutData
|
|
815
|
+
} from "@getstrata/core/view";
|
|
810
816
|
var CORE_VIEW_TOKEN = "core.view";
|
|
811
817
|
var VIEW_DIRECTORY_CONFIG_KEY = "view.directory";
|
|
812
818
|
var viewProvider = {
|
|
@@ -817,7 +823,15 @@ var viewProvider = {
|
|
|
817
823
|
}
|
|
818
824
|
const viewsDirectory = process.env.VIEW_DIRECTORY?.trim() || DEFAULT_VIEWS_DIRECTORY;
|
|
819
825
|
config.set(VIEW_DIRECTORY_CONFIG_KEY, viewsDirectory);
|
|
820
|
-
|
|
826
|
+
const engine = new EtaViewEngine(viewsDirectory, (request) => resolveWebLayoutData(container, request ?? currentRequestMeta().request));
|
|
827
|
+
container.set(CORE_VIEW_TOKEN, engine);
|
|
828
|
+
configureWebErrorView({
|
|
829
|
+
render: async (input) => engine.render(errorTemplateName(input.status), {
|
|
830
|
+
title: input.title,
|
|
831
|
+
message: input.message,
|
|
832
|
+
errors: input.errors
|
|
833
|
+
})
|
|
834
|
+
});
|
|
821
835
|
}
|
|
822
836
|
};
|
|
823
837
|
|
|
@@ -868,7 +882,7 @@ function createAppContext() {
|
|
|
868
882
|
}
|
|
869
883
|
// ../../src/bootstrap/createWebRoutes.ts
|
|
870
884
|
import { join as join3 } from "path";
|
|
871
|
-
import {
|
|
885
|
+
import { notFoundHtmlResponse } from "@getstrata/core/view";
|
|
872
886
|
function registerRoute(method, path, middleware) {
|
|
873
887
|
routeRegistry.register({ method, path, middleware });
|
|
874
888
|
}
|
|
@@ -886,7 +900,7 @@ function createWebRoutes(dependencies) {
|
|
|
886
900
|
const relativePath = pathname.replace(/^\//, "");
|
|
887
901
|
const file = Bun.file(join3(process.cwd(), "public", relativePath));
|
|
888
902
|
if (!await file.exists()) {
|
|
889
|
-
return
|
|
903
|
+
return notFoundHtmlResponse();
|
|
890
904
|
}
|
|
891
905
|
return new Response(file);
|
|
892
906
|
};
|
|
@@ -1201,10 +1215,21 @@ function createRouteKernel(dependencies) {
|
|
|
1201
1215
|
return createHttpKernel(dependencies);
|
|
1202
1216
|
}
|
|
1203
1217
|
// ../../src/bootstrap/web/server.ts
|
|
1218
|
+
import { currentRequestMeta as currentRequestMeta2, runWithRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
1219
|
+
import { notFoundHtmlResponse as notFoundHtmlResponse2 } from "@getstrata/core/view";
|
|
1220
|
+
async function missingHtmlResponse() {
|
|
1221
|
+
return notFoundHtmlResponse2();
|
|
1222
|
+
}
|
|
1204
1223
|
function wrapRouteHandler(handler) {
|
|
1205
1224
|
return async (request) => {
|
|
1206
|
-
|
|
1207
|
-
|
|
1225
|
+
return await runWithRequestMeta({
|
|
1226
|
+
...currentRequestMeta2(),
|
|
1227
|
+
request,
|
|
1228
|
+
userAgent: request.headers.get("user-agent")
|
|
1229
|
+
}, async () => {
|
|
1230
|
+
const response = await handler(request);
|
|
1231
|
+
return response ?? await missingHtmlResponse();
|
|
1232
|
+
});
|
|
1208
1233
|
};
|
|
1209
1234
|
}
|
|
1210
1235
|
function convertAppRoutesToBunRoutes(routes) {
|
|
@@ -1236,19 +1261,25 @@ function createWebServer(options) {
|
|
|
1236
1261
|
port: options.port,
|
|
1237
1262
|
...bunRoutes ? { routes: bunRoutes } : {},
|
|
1238
1263
|
async fetch(request) {
|
|
1239
|
-
await
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1264
|
+
return await runWithRequestMeta({
|
|
1265
|
+
...currentRequestMeta2(),
|
|
1266
|
+
request,
|
|
1267
|
+
userAgent: request.headers.get("user-agent")
|
|
1268
|
+
}, async () => {
|
|
1269
|
+
await options.onRequest?.(request);
|
|
1270
|
+
const url = new URL(request.url);
|
|
1271
|
+
if (url.pathname.startsWith("/assets/")) {
|
|
1272
|
+
const file = Bun.file(`${publicDir}${url.pathname}`);
|
|
1273
|
+
if (await file.exists()) {
|
|
1274
|
+
return new Response(file);
|
|
1275
|
+
}
|
|
1245
1276
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1277
|
+
if (options.handle) {
|
|
1278
|
+
const response = await options.handle(request);
|
|
1279
|
+
return response ?? await missingHtmlResponse();
|
|
1280
|
+
}
|
|
1281
|
+
return await missingHtmlResponse();
|
|
1282
|
+
});
|
|
1252
1283
|
}
|
|
1253
1284
|
});
|
|
1254
1285
|
}
|
|
@@ -1280,17 +1311,45 @@ function defaultMapSessionUser(user) {
|
|
|
1280
1311
|
role: user.is_admin ? "admin" : "member"
|
|
1281
1312
|
};
|
|
1282
1313
|
}
|
|
1314
|
+
async function defaultLoadSessionUser(sql, sessionId) {
|
|
1315
|
+
const rows = await sql.unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
1316
|
+
COALESCE(u.is_admin, false) AS is_admin
|
|
1317
|
+
FROM sessions s
|
|
1318
|
+
INNER JOIN users u ON u.id = s.user_id
|
|
1319
|
+
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
1320
|
+
const row = rows[0];
|
|
1321
|
+
if (!row)
|
|
1322
|
+
return null;
|
|
1323
|
+
return {
|
|
1324
|
+
id: row.user_id,
|
|
1325
|
+
name: row.name,
|
|
1326
|
+
email: row.email,
|
|
1327
|
+
learn_subscriber: row.learn_subscriber,
|
|
1328
|
+
is_admin: row.is_admin
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
function redirectWithCookie(location, setCookie, status) {
|
|
1332
|
+
return new Response(null, {
|
|
1333
|
+
status,
|
|
1334
|
+
headers: {
|
|
1335
|
+
Location: location,
|
|
1336
|
+
"Set-Cookie": setCookie
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1283
1340
|
|
|
1284
1341
|
class CookieSessionStore {
|
|
1285
1342
|
sqlSource;
|
|
1286
1343
|
secret;
|
|
1287
1344
|
cookieName;
|
|
1288
1345
|
maxAgeSeconds;
|
|
1289
|
-
|
|
1346
|
+
loadSessionUser;
|
|
1347
|
+
constructor(sqlSource, secret, cookieName = "strata_session", maxAgeSeconds = 60 * 60 * 24 * 14, loadSessionUser = defaultLoadSessionUser) {
|
|
1290
1348
|
this.sqlSource = sqlSource;
|
|
1291
1349
|
this.secret = secret;
|
|
1292
1350
|
this.cookieName = cookieName;
|
|
1293
1351
|
this.maxAgeSeconds = maxAgeSeconds;
|
|
1352
|
+
this.loadSessionUser = loadSessionUser;
|
|
1294
1353
|
}
|
|
1295
1354
|
cookieHeader(_user, sessionId) {
|
|
1296
1355
|
const payload = `${sessionId}.${this.sign(sessionId)}`;
|
|
@@ -1299,6 +1358,17 @@ class CookieSessionStore {
|
|
|
1299
1358
|
clearCookieHeader() {
|
|
1300
1359
|
return this.withSecureFlag(`${this.cookieName}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`);
|
|
1301
1360
|
}
|
|
1361
|
+
sessionIdFromRequest(request) {
|
|
1362
|
+
const cookie = readRequestCookie(request, this.cookieName);
|
|
1363
|
+
const raw = cookie ?? null;
|
|
1364
|
+
if (!raw)
|
|
1365
|
+
return null;
|
|
1366
|
+
const [sessionId, signature] = raw.split(".");
|
|
1367
|
+
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
1368
|
+
return null;
|
|
1369
|
+
}
|
|
1370
|
+
return sessionId;
|
|
1371
|
+
}
|
|
1302
1372
|
withSecureFlag(header) {
|
|
1303
1373
|
if (true) {
|
|
1304
1374
|
return header;
|
|
@@ -1322,29 +1392,10 @@ class CookieSessionStore {
|
|
|
1322
1392
|
await this.sql().unsafe(`DELETE FROM sessions WHERE id = $1`, [sessionId]);
|
|
1323
1393
|
}
|
|
1324
1394
|
async read(request) {
|
|
1325
|
-
const
|
|
1326
|
-
|
|
1327
|
-
if (!raw)
|
|
1395
|
+
const sessionId = this.sessionIdFromRequest(request);
|
|
1396
|
+
if (!sessionId)
|
|
1328
1397
|
return null;
|
|
1329
|
-
|
|
1330
|
-
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
1331
|
-
return null;
|
|
1332
|
-
}
|
|
1333
|
-
const rows = await this.sql().unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
1334
|
-
COALESCE(u.is_admin, false) AS is_admin
|
|
1335
|
-
FROM sessions s
|
|
1336
|
-
INNER JOIN users u ON u.id = s.user_id
|
|
1337
|
-
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
1338
|
-
const row = rows[0];
|
|
1339
|
-
if (!row)
|
|
1340
|
-
return null;
|
|
1341
|
-
return {
|
|
1342
|
-
id: row.user_id,
|
|
1343
|
-
name: row.name,
|
|
1344
|
-
email: row.email,
|
|
1345
|
-
learn_subscriber: row.learn_subscriber,
|
|
1346
|
-
is_admin: row.is_admin
|
|
1347
|
-
};
|
|
1398
|
+
return this.loadSessionUser(this.sql(), sessionId);
|
|
1348
1399
|
}
|
|
1349
1400
|
sign(value) {
|
|
1350
1401
|
return createHash("sha256").update(`${value}.${this.secret}`).digest("hex").slice(0, 32);
|
|
@@ -1366,9 +1417,36 @@ class CookieSessionGuard {
|
|
|
1366
1417
|
return this.mapUser(user);
|
|
1367
1418
|
}
|
|
1368
1419
|
}
|
|
1420
|
+
|
|
1421
|
+
class CookieSessionAuthManager extends AuthManager2 {
|
|
1422
|
+
store;
|
|
1423
|
+
constructor(store, mapUser = defaultMapSessionUser) {
|
|
1424
|
+
super(new CookieSessionGuard(store, mapUser));
|
|
1425
|
+
this.store = store;
|
|
1426
|
+
}
|
|
1427
|
+
async signIn(user) {
|
|
1428
|
+
const sessionId = await this.store.create(user);
|
|
1429
|
+
return { sessionId, setCookie: this.store.cookieHeader(user, sessionId) };
|
|
1430
|
+
}
|
|
1431
|
+
async signOut(request) {
|
|
1432
|
+
const sessionId = this.store.sessionIdFromRequest(request);
|
|
1433
|
+
if (sessionId) {
|
|
1434
|
+
await this.store.destroy(sessionId);
|
|
1435
|
+
}
|
|
1436
|
+
return { setCookie: this.store.clearCookieHeader() };
|
|
1437
|
+
}
|
|
1438
|
+
async signInRedirect(user, location, status = 302) {
|
|
1439
|
+
const { setCookie } = await this.signIn(user);
|
|
1440
|
+
return redirectWithCookie(location, setCookie, status);
|
|
1441
|
+
}
|
|
1442
|
+
async signOutRedirect(request, location, status = 302) {
|
|
1443
|
+
const { setCookie } = await this.signOut(request);
|
|
1444
|
+
return redirectWithCookie(location, setCookie, status);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1369
1447
|
function createCookieSessionAuthManager(options = {}) {
|
|
1370
|
-
const store = options.store ?? new CookieSessionStore(options.sql ?? defaultSessionSql, options.secret ?? process.env.SESSION_SECRET?.trim() ?? "", options.cookieName, options.maxAgeSeconds);
|
|
1371
|
-
return new
|
|
1448
|
+
const store = options.store ?? new CookieSessionStore(options.sql ?? defaultSessionSql, options.secret ?? process.env.SESSION_SECRET?.trim() ?? "", options.cookieName, options.maxAgeSeconds, options.loadSessionUser);
|
|
1449
|
+
return new CookieSessionAuthManager(store, options.mapUser ?? defaultMapSessionUser);
|
|
1372
1450
|
}
|
|
1373
1451
|
// ../../src/bootstrap/web/slug.ts
|
|
1374
1452
|
function slugify(value) {
|
|
@@ -1385,6 +1463,7 @@ export {
|
|
|
1385
1463
|
CORE_POLICY_GATE_TOKEN,
|
|
1386
1464
|
CORE_QUEUE_TOKEN,
|
|
1387
1465
|
CORE_TOKEN_SERVICE_TOKEN,
|
|
1466
|
+
CookieSessionAuthManager,
|
|
1388
1467
|
CookieSessionGuard,
|
|
1389
1468
|
CookieSessionStore,
|
|
1390
1469
|
DATABASE_URL_CONFIG_KEY,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.52",
|
|
4
4
|
"description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -173,14 +173,14 @@
|
|
|
173
173
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external @getstrata/core",
|
|
174
174
|
"build:types": "tsc -p tsconfig.types.json && bun ../../scripts/prune-bootstrap-dist-types.ts",
|
|
175
175
|
"prepublishOnly": "bun run build",
|
|
176
|
-
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.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 --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/guard --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/connection --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/dispatchWebhookJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
176
|
+
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.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 --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/guard --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/bunSql --external @getstrata/core/database/connection --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/contentSecurityPolicy --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/safeInternalPath --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/dispatchWebhookJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
177
177
|
"build:shims": "true"
|
|
178
178
|
},
|
|
179
179
|
"publishConfig": {
|
|
180
180
|
"access": "public"
|
|
181
181
|
},
|
|
182
182
|
"peerDependencies": {
|
|
183
|
-
"@getstrata/core": "^0.5.
|
|
183
|
+
"@getstrata/core": "^0.5.61",
|
|
184
184
|
"typescript": "^5.9.0"
|
|
185
185
|
}
|
|
186
186
|
}
|