@getstrata/bootstrap 0.2.23 → 0.2.26
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/applicationRegistry.d.ts +1 -1
- package/dist/bootstrap/buildWebModuleRoutes.d.ts +9 -0
- package/dist/bootstrap/config.d.ts +1 -1
- package/dist/bootstrap/env.d.ts +1 -1
- package/dist/bootstrap/membershipService.d.ts +1 -1
- package/dist/bootstrap/public-api.d.ts +4 -2
- package/dist/bootstrap/routeRegistry.d.ts +1 -1
- package/dist/entries/applicationRegistry.js +1 -1
- package/dist/entries/buildModuleRoutes.js +4 -219
- package/dist/entries/buildWebModuleRoutes.js +435 -0
- package/dist/entries/config.js +1 -1
- package/dist/entries/context.js +3 -19
- package/dist/entries/createWebRoutes.js +100 -682
- package/dist/entries/dependencies.js +3 -19
- package/dist/entries/http/securedRouteModelBinding.js +0 -7
- package/dist/entries/httpKernel.js +1 -1
- package/dist/entries/membershipService.js +2 -392
- package/dist/entries/providers/view.js +1 -12
- package/dist/entries/providers.js +3 -19
- package/dist/entries/queue/defaultJobs.js +0 -3
- package/dist/entries/web/routing.js +1 -8
- package/dist/index.js +139 -373
- package/package.json +8 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationEventBus, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "@getstrata/core/runtime/applicationRegistry
|
|
1
|
+
export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationEventBus, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "@getstrata/core/runtime/applicationRegistry";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AppDependencies, AppModule, AppRouteMap } from "./contracts";
|
|
2
|
+
interface BuildWebModuleRoutesOptions {
|
|
3
|
+
modules?: AppModule[];
|
|
4
|
+
clearRegistry?: boolean;
|
|
5
|
+
seedRoutes?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
declare function buildWebModuleRoutes(dependencies: AppDependencies, options?: BuildWebModuleRoutesOptions): AppRouteMap;
|
|
8
|
+
export type { BuildWebModuleRoutesOptions };
|
|
9
|
+
export { buildWebModuleRoutes };
|
|
@@ -4,7 +4,7 @@ declare const CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
|
4
4
|
declare const CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
5
5
|
declare const REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
6
6
|
declare const DATABASE_URL_CONFIG_KEY = "database.url";
|
|
7
|
-
export { CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, } from "@getstrata/core/contracts/serviceTokens
|
|
7
|
+
export { CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, } from "@getstrata/core/contracts/serviceTokens";
|
|
8
8
|
declare const AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
9
9
|
declare const DEFAULT_APP_PORT = 3000;
|
|
10
10
|
declare const DEFAULT_CACHE_TTL_MS = 3600000;
|
package/dist/bootstrap/env.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { resolveMembershipService } from "
|
|
1
|
+
export { resolveMembershipService } from "@getstrata/core/auth/membershipService";
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @getstrata/bootstrap — application shell for Strata sibling apps.
|
|
3
3
|
*/
|
|
4
|
+
export type { ScheduledTask } from "@getstrata/core/scheduler/schedule";
|
|
5
|
+
export { appSchedule, runDueScheduledTasks, Schedule } from "@getstrata/core/scheduler/schedule";
|
|
4
6
|
export { scheduleRunCommand } from "../cli/commands/scheduleRun.ts";
|
|
5
|
-
export type { ScheduledTask } from "../core/scheduler/schedule.ts";
|
|
6
|
-
export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
|
|
7
7
|
export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationEventBus, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "./applicationRegistry.ts";
|
|
8
8
|
export type { BuildModuleRoutesOptions } from "./buildModuleRoutes.ts";
|
|
9
9
|
export { buildModuleRoutes } from "./buildModuleRoutes.ts";
|
|
10
|
+
export type { BuildWebModuleRoutesOptions } from "./buildWebModuleRoutes.ts";
|
|
11
|
+
export { buildWebModuleRoutes } from "./buildWebModuleRoutes.ts";
|
|
10
12
|
export { cacheTagsForModelWrite, discoverModelTableNames } from "./cache/modelCacheTags.ts";
|
|
11
13
|
export { APP_PORT_CONFIG_KEY, CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, DATABASE_URL_CONFIG_KEY, DEFAULT_APP_PORT, REDIS_URL_CONFIG_KEY, } from "./config.ts";
|
|
12
14
|
export { collectProviders, createAppContext, runProviderPhase } from "./context.ts";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
resolveApplicationPolicyGate,
|
|
11
11
|
resolveApplicationQueue,
|
|
12
12
|
setActiveApplicationContext
|
|
13
|
-
} from "@getstrata/core/runtime/applicationRegistry
|
|
13
|
+
} from "@getstrata/core/runtime/applicationRegistry";
|
|
14
14
|
export {
|
|
15
15
|
setActiveApplicationContext,
|
|
16
16
|
resolveApplicationQueue,
|
|
@@ -1,222 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// ../../src/
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// ../../src/core/errors/http.ts
|
|
8
|
-
class HttpError extends Error {
|
|
9
|
-
status;
|
|
10
|
-
details;
|
|
11
|
-
constructor(status, message, details) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.name = new.target.name;
|
|
14
|
-
this.status = status;
|
|
15
|
-
this.details = details;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
class BadRequestError extends HttpError {
|
|
20
|
-
constructor(message = "Bad Request", details) {
|
|
21
|
-
super(400, message, details);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
class ConflictError extends HttpError {
|
|
25
|
-
constructor(message = "Conflict", details) {
|
|
26
|
-
super(409, message, details);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
class UnprocessableEntityError extends HttpError {
|
|
31
|
-
constructor(message = "Unprocessable Entity", details) {
|
|
32
|
-
super(422, message, details);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
class ForbiddenError extends HttpError {
|
|
36
|
-
constructor(message = "Forbidden", details) {
|
|
37
|
-
super(403, message, details);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
class UnauthorizedError extends HttpError {
|
|
42
|
-
constructor(message = "Unauthorized", details) {
|
|
43
|
-
super(401, message, details);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
class PreconditionFailedError extends HttpError {
|
|
47
|
-
constructor(message = "Precondition Failed", details) {
|
|
48
|
-
super(412, message, details);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ../../src/core/http/etag.ts
|
|
53
|
-
function isEtagEnabled() {
|
|
54
|
-
return (process.env.FEATURE_ETAG ?? "true") !== "false";
|
|
55
|
-
}
|
|
56
|
-
function formatWeakEtag(digest) {
|
|
57
|
-
return `W/"${digest}"`;
|
|
58
|
-
}
|
|
59
|
-
function computeEtagFromJson(data) {
|
|
60
|
-
const digest = nonCryptographicDigest(JSON.stringify(data)).slice(0, 32);
|
|
61
|
-
return formatWeakEtag(digest);
|
|
62
|
-
}
|
|
63
|
-
function etagFromResource(resource) {
|
|
64
|
-
const version = resource.updated_at ?? resource.created_at ?? "";
|
|
65
|
-
const versionText = version instanceof Date ? version.toISOString() : version ? String(version) : "0";
|
|
66
|
-
const digest = nonCryptographicDigest(`${String(resource.id ?? "0")}:${versionText}`).slice(0, 32);
|
|
67
|
-
return formatWeakEtag(digest);
|
|
68
|
-
}
|
|
69
|
-
function normalizeEtag(value) {
|
|
70
|
-
return value.trim();
|
|
71
|
-
}
|
|
72
|
-
function etagValuesMatch(left, right) {
|
|
73
|
-
return normalizeEtag(left) === normalizeEtag(right);
|
|
74
|
-
}
|
|
75
|
-
function parseEtagList(header) {
|
|
76
|
-
if (!header) {
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
return header.split(",").map((value) => normalizeEtag(value)).filter(Boolean);
|
|
80
|
-
}
|
|
81
|
-
function ifNoneMatchSatisfied(request, etag) {
|
|
82
|
-
const header = request.headers.get("if-none-match");
|
|
83
|
-
if (!header) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
if (header.trim() === "*") {
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
return parseEtagList(header).some((candidate) => etagValuesMatch(candidate, etag));
|
|
90
|
-
}
|
|
91
|
-
function ifMatchSatisfied(request, etag) {
|
|
92
|
-
const header = request.headers.get("if-match");
|
|
93
|
-
if (!header) {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
if (header.trim() === "*") {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
return parseEtagList(header).some((candidate) => etagValuesMatch(candidate, etag));
|
|
100
|
-
}
|
|
101
|
-
function assertIfMatch(request, etag, options = {}) {
|
|
102
|
-
const header = request.headers.get("if-match");
|
|
103
|
-
if (!header) {
|
|
104
|
-
if (options.required) {
|
|
105
|
-
throw new PreconditionFailedError("If-Match header is required.");
|
|
106
|
-
}
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (!ifMatchSatisfied(request, etag)) {
|
|
110
|
-
throw new PreconditionFailedError("Resource ETag does not match If-Match.");
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
function applyEtagHeaders(headers, etag) {
|
|
114
|
-
const next = new Headers(headers);
|
|
115
|
-
next.set("ETag", etag);
|
|
116
|
-
next.set("Cache-Control", "private, must-revalidate");
|
|
117
|
-
next.append("Vary", "Authorization");
|
|
118
|
-
next.append("Vary", "X-Tenant-Id");
|
|
119
|
-
return next;
|
|
120
|
-
}
|
|
121
|
-
function notModifiedResponse(etag) {
|
|
122
|
-
return new Response(null, {
|
|
123
|
-
status: 304,
|
|
124
|
-
headers: applyEtagHeaders(new Headers, etag)
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
function applyConditionalGet(request, response, etag) {
|
|
128
|
-
if (!isEtagEnabled()) {
|
|
129
|
-
return response;
|
|
130
|
-
}
|
|
131
|
-
if (ifNoneMatchSatisfied(request, etag)) {
|
|
132
|
-
return notModifiedResponse(etag);
|
|
133
|
-
}
|
|
134
|
-
const headers = applyEtagHeaders(new Headers(response.headers), etag);
|
|
135
|
-
return new Response(response.body, {
|
|
136
|
-
status: response.status,
|
|
137
|
-
statusText: response.statusText,
|
|
138
|
-
headers
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// ../../src/core/http/conditionalResponse.ts
|
|
143
|
-
function jsonResponse(data, init = {}) {
|
|
144
|
-
return Response.json(data, {
|
|
145
|
-
status: init.status ?? 200,
|
|
146
|
-
headers: init.headers
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
function conditionalJsonResponse(request, data, init = {}) {
|
|
150
|
-
if (!request || !isEtagEnabled()) {
|
|
151
|
-
return jsonResponse(data, init);
|
|
152
|
-
}
|
|
153
|
-
const etag = computeEtagFromJson(data);
|
|
154
|
-
if (ifNoneMatchSatisfied(request, etag)) {
|
|
155
|
-
return notModifiedResponse(etag);
|
|
156
|
-
}
|
|
157
|
-
const response = jsonResponse(data, init);
|
|
158
|
-
const headers = new Headers(response.headers);
|
|
159
|
-
headers.set("ETag", etag);
|
|
160
|
-
headers.set("Cache-Control", "private, must-revalidate");
|
|
161
|
-
headers.append("Vary", "Authorization");
|
|
162
|
-
headers.append("Vary", "X-Tenant-Id");
|
|
163
|
-
return new Response(response.body, {
|
|
164
|
-
status: response.status,
|
|
165
|
-
statusText: response.statusText,
|
|
166
|
-
headers
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// ../../src/core/http/middleware.ts
|
|
171
|
-
function isRouteHandler(value) {
|
|
172
|
-
return typeof value === "function";
|
|
173
|
-
}
|
|
174
|
-
function isMethodRouteMap(value) {
|
|
175
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
const entries = Object.entries(value);
|
|
179
|
-
return entries.length > 0 && entries.every(([, handler]) => isRouteHandler(handler));
|
|
180
|
-
}
|
|
181
|
-
function composeMiddleware(...middleware) {
|
|
182
|
-
return (handler) => {
|
|
183
|
-
return async (request) => {
|
|
184
|
-
let index = 0;
|
|
185
|
-
const dispatch = async () => {
|
|
186
|
-
if (index >= middleware.length) {
|
|
187
|
-
return await handler(request);
|
|
188
|
-
}
|
|
189
|
-
const current = middleware[index];
|
|
190
|
-
index += 1;
|
|
191
|
-
if (!current) {
|
|
192
|
-
return await handler(request);
|
|
193
|
-
}
|
|
194
|
-
return await current(request, dispatch);
|
|
195
|
-
};
|
|
196
|
-
return await dispatch();
|
|
197
|
-
};
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
function wrapRouteHandler(handler, middleware) {
|
|
201
|
-
if (isMethodRouteMap(handler)) {
|
|
202
|
-
const wrapped = {};
|
|
203
|
-
for (const [method, routeHandler] of Object.entries(handler)) {
|
|
204
|
-
wrapped[method] = composeMiddleware(...middleware)(routeHandler);
|
|
205
|
-
}
|
|
206
|
-
return wrapped;
|
|
207
|
-
}
|
|
208
|
-
if (isRouteHandler(handler)) {
|
|
209
|
-
return composeMiddleware(...middleware)(handler);
|
|
210
|
-
}
|
|
211
|
-
return handler;
|
|
212
|
-
}
|
|
213
|
-
function applyMiddlewareToRoutes(routes, middleware) {
|
|
214
|
-
const wrapped = {};
|
|
215
|
-
for (const [path, routeHandler] of Object.entries(routes)) {
|
|
216
|
-
wrapped[path] = wrapRouteHandler(routeHandler, middleware);
|
|
217
|
-
}
|
|
218
|
-
return wrapped;
|
|
219
|
-
}
|
|
2
|
+
// ../../src/bootstrap/buildModuleRoutes.ts
|
|
3
|
+
import { conditionalJsonResponse } from "@getstrata/core/http";
|
|
4
|
+
import { applyMiddlewareToRoutes } from "@getstrata/core/http/middleware";
|
|
220
5
|
|
|
221
6
|
// ../../src/bootstrap/httpKernel.ts
|
|
222
7
|
import {
|
|
@@ -302,7 +87,7 @@ import {
|
|
|
302
87
|
CORE_POLICY_GATE_TOKEN,
|
|
303
88
|
CORE_QUEUE_TOKEN,
|
|
304
89
|
CORE_TOKEN_SERVICE_TOKEN
|
|
305
|
-
} from "@getstrata/core/contracts/serviceTokens
|
|
90
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
306
91
|
var APP_PORT_CONFIG_KEY = "app.port";
|
|
307
92
|
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
308
93
|
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|