@dudousxd/nestjs-durable-dashboard 0.53.0 → 0.55.0
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/client/durable-client.d.ts +67 -3
- package/dist/client/durable-client.d.ts.map +1 -1
- package/dist/client/durable-client.js +26 -46
- package/dist/client/durable-client.js.map +1 -1
- package/dist/client/event-tail.d.ts +25 -0
- package/dist/client/event-tail.d.ts.map +1 -0
- package/dist/client/event-tail.js +30 -0
- package/dist/client/event-tail.js.map +1 -0
- package/dist/server/index.cjs +322 -1337
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +149 -389
- package/dist/server/index.d.ts +149 -389
- package/dist/server/index.js +308 -1317
- package/dist/server/index.js.map +1 -1
- package/dist/spa/assets/{bench-Db-gqOEF.js → bench-DCclNvcZ.js} +1 -1
- package/dist/spa/assets/index-B-wtX4GV.js +66 -0
- package/dist/spa/assets/index-CJdk28vt.css +1 -0
- package/dist/spa/assets/{index-4tEXGRlA.js → index-ChjKRQZx.js} +1 -1
- package/dist/spa/assets/{preview-BvCp1zR5.js → preview-CdsjvOrK.js} +1 -1
- package/dist/spa/bench.html +3 -3
- package/dist/spa/index.html +3 -3
- package/dist/spa/preview.html +3 -3
- package/package.json +5 -18
- package/dist/client/console-session.d.ts +0 -63
- package/dist/client/console-session.d.ts.map +0 -1
- package/dist/client/console-session.js +0 -107
- package/dist/client/console-session.js.map +0 -1
- package/dist/react/index.d.ts +0 -4
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -14
- package/dist/react/index.js.map +0 -1
- package/dist/react/open-console-button.d.ts +0 -26
- package/dist/react/open-console-button.d.ts.map +0 -1
- package/dist/react/open-console-button.js +0 -26
- package/dist/react/open-console-button.js.map +0 -1
- package/dist/react/use-open-console.d.ts +0 -40
- package/dist/react/use-open-console.d.ts.map +0 -1
- package/dist/react/use-open-console.js +0 -77
- package/dist/react/use-open-console.js.map +0 -1
- package/dist/spa/assets/index-BbR4CZ1K.css +0 -1
- package/dist/spa/assets/index-CEV7yPmk.js +0 -66
package/dist/server/index.cjs
CHANGED
|
@@ -24,21 +24,15 @@ var index_exports = {};
|
|
|
24
24
|
__export(index_exports, {
|
|
25
25
|
DASHBOARD_API_PATH: () => DASHBOARD_API_PATH,
|
|
26
26
|
DASHBOARD_BASE_PATH: () => DASHBOARD_BASE_PATH,
|
|
27
|
-
|
|
28
|
-
DURABLE_DASHBOARD_TOKEN_ENV: () => DURABLE_DASHBOARD_TOKEN_ENV,
|
|
27
|
+
DASHBOARD_PROTECTION_CHECK: () => DASHBOARD_PROTECTION_CHECK,
|
|
29
28
|
DashboardService: () => DashboardService,
|
|
30
29
|
DurableApiController: () => DurableApiController,
|
|
30
|
+
DurableApiControllerBase: () => DurableApiControllerBase,
|
|
31
31
|
DurableApiModule: () => DurableApiModule,
|
|
32
|
-
DurableApiSessionGuard: () => DurableApiSessionGuard,
|
|
33
|
-
DurableAuthController: () => DurableAuthController,
|
|
34
|
-
DurableDashboardGateGuard: () => DurableDashboardGateGuard,
|
|
35
32
|
DurableDashboardModule: () => DurableDashboardModule,
|
|
36
33
|
DurableUiController: () => DurableUiController,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
readDashboardToken: () => readDashboardToken,
|
|
40
|
-
reportDashboardGate: () => reportDashboardGate,
|
|
41
|
-
resolveDashboardGate: () => resolveDashboardGate
|
|
34
|
+
DurableUiControllerBase: () => DurableUiControllerBase,
|
|
35
|
+
UNPROTECTED_CONSOLE_IN_PRODUCTION: () => UNPROTECTED_CONSOLE_IN_PRODUCTION
|
|
42
36
|
});
|
|
43
37
|
module.exports = __toCommonJS(index_exports);
|
|
44
38
|
|
|
@@ -215,6 +209,51 @@ var DashboardService = class {
|
|
|
215
209
|
return this.gateway.cancel(runId, opts);
|
|
216
210
|
}
|
|
217
211
|
/**
|
|
212
|
+
* Publish a settled run's lifecycle event again, to its subscribers that have not started (or to
|
|
213
|
+
* `subscriber` alone). Undefined when the gateway cannot republish (a tenant proxy).
|
|
214
|
+
*/
|
|
215
|
+
async republishLifecycle(runId, subscriber) {
|
|
216
|
+
return this.gateway.republishLifecycle?.({
|
|
217
|
+
runId,
|
|
218
|
+
...subscriber !== void 0 ? {
|
|
219
|
+
subscriber
|
|
220
|
+
} : {}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Who starts whom through lifecycle events, for `workflow`, plus `triggerCounts` when this process
|
|
225
|
+
* counts the engine's events (the control plane) and the workflow has subscribers. Undefined when
|
|
226
|
+
* the gateway cannot answer.
|
|
227
|
+
*/
|
|
228
|
+
async workflowLifecycle(workflow) {
|
|
229
|
+
const links = await this.gateway.workflowLifecycle?.(workflow);
|
|
230
|
+
if (!links) return links;
|
|
231
|
+
const counts = this.triggerCountsOf(links);
|
|
232
|
+
return counts ? {
|
|
233
|
+
...links,
|
|
234
|
+
triggerCounts: counts
|
|
235
|
+
} : links;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* How many runs each subscriber of `links.workflow` was started for and how many times starting it
|
|
239
|
+
* failed, counted by this process's metrics since it started. Undefined without metrics (a tenant)
|
|
240
|
+
* or without subscribers.
|
|
241
|
+
*/
|
|
242
|
+
triggerCountsOf(links) {
|
|
243
|
+
const snapshot = this.metricsCollector?.snapshot();
|
|
244
|
+
if (!snapshot || links.startsOnSettle.length === 0) return void 0;
|
|
245
|
+
const triggered = snapshot.triggeredBySubscriber[links.workflow] ?? {};
|
|
246
|
+
const failed = snapshot.triggerFailedBySubscriber[links.workflow] ?? {};
|
|
247
|
+
const counts = {};
|
|
248
|
+
for (const { workflow } of links.startsOnSettle) {
|
|
249
|
+
counts[workflow] = {
|
|
250
|
+
triggered: triggered[workflow] ?? 0,
|
|
251
|
+
failed: failed[workflow] ?? 0
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
return counts;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
218
257
|
* Apply `retry` or `cancel` to every run matching a filter (status / tag / workflow / namespace /
|
|
219
258
|
* origin) — e.g. "retry every `dead` run tagged `type:mel`". The filter is the same one the run
|
|
220
259
|
* list uses, so a bulk action can never reach wider than the list it was launched from — but note
|
|
@@ -392,87 +431,6 @@ __name(runValueAxisFor, "runValueAxisFor");
|
|
|
392
431
|
|
|
393
432
|
// src/server/not-modified.ts
|
|
394
433
|
var import_common2 = require("@nestjs/common");
|
|
395
|
-
|
|
396
|
-
// src/server/auth/response.ts
|
|
397
|
-
function isRecord(value) {
|
|
398
|
-
return typeof value === "object" && value !== null;
|
|
399
|
-
}
|
|
400
|
-
__name(isRecord, "isRecord");
|
|
401
|
-
function isRawCookieResponse(value) {
|
|
402
|
-
return isRecord(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function";
|
|
403
|
-
}
|
|
404
|
-
__name(isRawCookieResponse, "isRawCookieResponse");
|
|
405
|
-
function resolveCookieResponse(response) {
|
|
406
|
-
if (isRawCookieResponse(response)) return response;
|
|
407
|
-
if (isRecord(response) && isRawCookieResponse(response.raw)) return response.raw;
|
|
408
|
-
return null;
|
|
409
|
-
}
|
|
410
|
-
__name(resolveCookieResponse, "resolveCookieResponse");
|
|
411
|
-
function existingSetCookies(response) {
|
|
412
|
-
const current = response.getHeader("set-cookie");
|
|
413
|
-
if (Array.isArray(current)) return current;
|
|
414
|
-
if (typeof current === "string") return [
|
|
415
|
-
current
|
|
416
|
-
];
|
|
417
|
-
return [];
|
|
418
|
-
}
|
|
419
|
-
__name(existingSetCookies, "existingSetCookies");
|
|
420
|
-
function appendSetCookie(response, cookie) {
|
|
421
|
-
const raw = resolveCookieResponse(response);
|
|
422
|
-
if (!raw) return;
|
|
423
|
-
raw.setHeader("set-cookie", [
|
|
424
|
-
...existingSetCookies(raw),
|
|
425
|
-
cookie
|
|
426
|
-
]);
|
|
427
|
-
}
|
|
428
|
-
__name(appendSetCookie, "appendSetCookie");
|
|
429
|
-
function isRawRedirectResponse(value) {
|
|
430
|
-
return isRecord(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function" && typeof value.end === "function";
|
|
431
|
-
}
|
|
432
|
-
__name(isRawRedirectResponse, "isRawRedirectResponse");
|
|
433
|
-
function resolveRedirectResponse(response) {
|
|
434
|
-
if (isRawRedirectResponse(response)) return response;
|
|
435
|
-
if (isRecord(response) && isRawRedirectResponse(response.raw)) return response.raw;
|
|
436
|
-
return null;
|
|
437
|
-
}
|
|
438
|
-
__name(resolveRedirectResponse, "resolveRedirectResponse");
|
|
439
|
-
function redirectRaw(response, location, status = 302) {
|
|
440
|
-
const raw = resolveRedirectResponse(response);
|
|
441
|
-
if (!raw) return;
|
|
442
|
-
raw.statusCode = status;
|
|
443
|
-
raw.setHeader("location", location);
|
|
444
|
-
raw.end();
|
|
445
|
-
}
|
|
446
|
-
__name(redirectRaw, "redirectRaw");
|
|
447
|
-
function responseAlreadyWritten(response) {
|
|
448
|
-
const raw = resolveRedirectResponse(response);
|
|
449
|
-
return raw?.headersSent === true;
|
|
450
|
-
}
|
|
451
|
-
__name(responseAlreadyWritten, "responseAlreadyWritten");
|
|
452
|
-
function writeHtmlRaw(response, html, status = 200) {
|
|
453
|
-
const raw = resolveRedirectResponse(response);
|
|
454
|
-
if (!raw) return;
|
|
455
|
-
raw.statusCode = status;
|
|
456
|
-
raw.setHeader("content-type", "text/html; charset=utf-8");
|
|
457
|
-
raw.setHeader("cache-control", "no-store, must-revalidate");
|
|
458
|
-
raw.end(html);
|
|
459
|
-
}
|
|
460
|
-
__name(writeHtmlRaw, "writeHtmlRaw");
|
|
461
|
-
function setRawHeader(response, name, value) {
|
|
462
|
-
resolveCookieResponse(response)?.setHeader(name, value);
|
|
463
|
-
}
|
|
464
|
-
__name(setRawHeader, "setRawHeader");
|
|
465
|
-
function writeNotModifiedRaw(response, etag) {
|
|
466
|
-
const raw = resolveRedirectResponse(response);
|
|
467
|
-
if (!raw) return;
|
|
468
|
-
raw.statusCode = 304;
|
|
469
|
-
raw.setHeader("etag", etag);
|
|
470
|
-
raw.setHeader("cache-control", "private, no-cache");
|
|
471
|
-
raw.end();
|
|
472
|
-
}
|
|
473
|
-
__name(writeNotModifiedRaw, "writeNotModifiedRaw");
|
|
474
|
-
|
|
475
|
-
// src/server/not-modified.ts
|
|
476
434
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
477
435
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
478
436
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -487,6 +445,31 @@ function _ts_decorate2(decorators, target, key, desc) {
|
|
|
487
445
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
488
446
|
}
|
|
489
447
|
__name(_ts_decorate2, "_ts_decorate");
|
|
448
|
+
function isRawResponse(value) {
|
|
449
|
+
if (typeof value !== "object" || value === null) return false;
|
|
450
|
+
const candidate = value;
|
|
451
|
+
return typeof candidate.setHeader === "function" && typeof candidate.end === "function";
|
|
452
|
+
}
|
|
453
|
+
__name(isRawResponse, "isRawResponse");
|
|
454
|
+
function rawResponse(response) {
|
|
455
|
+
if (isRawResponse(response)) return response;
|
|
456
|
+
const raw = response?.raw;
|
|
457
|
+
return isRawResponse(raw) ? raw : null;
|
|
458
|
+
}
|
|
459
|
+
__name(rawResponse, "rawResponse");
|
|
460
|
+
function setRawHeader(response, name, value) {
|
|
461
|
+
rawResponse(response)?.setHeader(name, value);
|
|
462
|
+
}
|
|
463
|
+
__name(setRawHeader, "setRawHeader");
|
|
464
|
+
function writeNotModifiedRaw(response, etag) {
|
|
465
|
+
const raw = rawResponse(response);
|
|
466
|
+
if (!raw) return;
|
|
467
|
+
raw.statusCode = 304;
|
|
468
|
+
raw.setHeader("etag", etag);
|
|
469
|
+
raw.setHeader("cache-control", "private, no-cache");
|
|
470
|
+
raw.end();
|
|
471
|
+
}
|
|
472
|
+
__name(writeNotModifiedRaw, "writeNotModifiedRaw");
|
|
490
473
|
var NotModifiedException = class extends import_common2.HttpException {
|
|
491
474
|
static {
|
|
492
475
|
__name(this, "NotModifiedException");
|
|
@@ -802,10 +785,10 @@ var RunQueryAdapter = class {
|
|
|
802
785
|
}
|
|
803
786
|
unsupported(clause, "equals, notEquals, gt, gte, lt, lte, in");
|
|
804
787
|
}
|
|
805
|
-
applyOffsetPagination(qb,
|
|
788
|
+
applyOffsetPagination(qb, page, size) {
|
|
806
789
|
this.draft(qb).narrow({
|
|
807
790
|
limit: size,
|
|
808
|
-
offset: (
|
|
791
|
+
offset: (page - 1) * size
|
|
809
792
|
});
|
|
810
793
|
}
|
|
811
794
|
/**
|
|
@@ -1149,9 +1132,9 @@ function _ts_param2(paramIndex, decorator) {
|
|
|
1149
1132
|
}
|
|
1150
1133
|
__name(_ts_param2, "_ts_param");
|
|
1151
1134
|
var FAN_INLINE_MAX = 50;
|
|
1152
|
-
var
|
|
1135
|
+
var DurableApiControllerBase = class {
|
|
1153
1136
|
static {
|
|
1154
|
-
__name(this, "
|
|
1137
|
+
__name(this, "DurableApiControllerBase");
|
|
1155
1138
|
}
|
|
1156
1139
|
dashboard;
|
|
1157
1140
|
runner;
|
|
@@ -1243,6 +1226,15 @@ var DurableApiController = class {
|
|
|
1243
1226
|
triggerSchedule(id) {
|
|
1244
1227
|
return this.dashboard.triggerSchedule(id).catch(notFound);
|
|
1245
1228
|
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Who starts whom through lifecycle events, for one workflow: the workflows that start when it
|
|
1231
|
+
* settles, and the ones whose settling starts it. What the console's workflow page lists.
|
|
1232
|
+
*/
|
|
1233
|
+
async workflowLifecycle(name) {
|
|
1234
|
+
const links = await this.dashboard.workflowLifecycle(name).catch(notSupportedByServer);
|
|
1235
|
+
if (!links) throw new import_common5.NotImplementedException("workflow lifecycle links need the control plane");
|
|
1236
|
+
return links;
|
|
1237
|
+
}
|
|
1246
1238
|
/** This deployment's durable role (control plane vs tenant) + tenant name — for the header badge. */
|
|
1247
1239
|
topology() {
|
|
1248
1240
|
return this.dashboard.topology();
|
|
@@ -1272,7 +1264,7 @@ var DurableApiController = class {
|
|
|
1272
1264
|
}
|
|
1273
1265
|
/** One page of a summarized fan's members, in seq order. Versioned like {@link run}. */
|
|
1274
1266
|
async fanMembers(id, group, offset, limit, failed, ifNoneMatch, response) {
|
|
1275
|
-
const
|
|
1267
|
+
const page = await this.dashboard.getFanMembers(id, group, {
|
|
1276
1268
|
offset: offset === void 0 ? void 0 : Number(offset),
|
|
1277
1269
|
limit: limit === void 0 ? void 0 : Number(limit),
|
|
1278
1270
|
failedOnly: failed === "true",
|
|
@@ -1280,8 +1272,8 @@ var DurableApiController = class {
|
|
|
1280
1272
|
ifNoneMatch
|
|
1281
1273
|
}
|
|
1282
1274
|
});
|
|
1283
|
-
if (!
|
|
1284
|
-
const { etag, notModified, ...body } =
|
|
1275
|
+
if (!page) throw new import_common5.NotFoundException(`fan ${group} of run ${id} not found`);
|
|
1276
|
+
const { etag, notModified, ...body } = page;
|
|
1285
1277
|
if (etag) {
|
|
1286
1278
|
if (notModified) throw new NotModifiedException(etag);
|
|
1287
1279
|
setEtag(response, etag);
|
|
@@ -1318,6 +1310,28 @@ var DurableApiController = class {
|
|
|
1318
1310
|
if (!result) throw new import_common5.NotFoundException(`run ${id} not found`);
|
|
1319
1311
|
return result;
|
|
1320
1312
|
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Publish a settled run's lifecycle event again, to the subscribers that have not started from it
|
|
1315
|
+
* (or only `subscriber`). Same gate as retry/cancel.
|
|
1316
|
+
*/
|
|
1317
|
+
async republishLifecycle(id, body) {
|
|
1318
|
+
let result;
|
|
1319
|
+
try {
|
|
1320
|
+
result = await this.dashboard.republishLifecycle(id, body?.subscriber || void 0);
|
|
1321
|
+
} catch (error) {
|
|
1322
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1323
|
+
if (/^run .* not found$/.test(message)) throw new import_common5.NotFoundException(message);
|
|
1324
|
+
if (/^run .* has not settled/.test(message)) throw new import_common5.BadRequestException(message);
|
|
1325
|
+
if (error?.code === "bad-request") {
|
|
1326
|
+
throw new import_common5.BadRequestException(message);
|
|
1327
|
+
}
|
|
1328
|
+
return notSupportedByServer(error);
|
|
1329
|
+
}
|
|
1330
|
+
if (!result) {
|
|
1331
|
+
throw new import_common5.NotImplementedException("republishing lifecycle events needs the control plane");
|
|
1332
|
+
}
|
|
1333
|
+
return result;
|
|
1334
|
+
}
|
|
1321
1335
|
async continue(id) {
|
|
1322
1336
|
const result = await this.dashboard.continue(id);
|
|
1323
1337
|
if (!result) throw new import_common5.NotFoundException(`run ${id} is not paused at a breakpoint`);
|
|
@@ -1357,7 +1371,7 @@ _ts_decorate5([
|
|
|
1357
1371
|
typeof RunQueryDraft === "undefined" ? Object : RunQueryDraft
|
|
1358
1372
|
]),
|
|
1359
1373
|
_ts_metadata4("design:returntype", Promise)
|
|
1360
|
-
],
|
|
1374
|
+
], DurableApiControllerBase.prototype, "runs", null);
|
|
1361
1375
|
_ts_decorate5([
|
|
1362
1376
|
(0, import_common5.Get)("runs/facets"),
|
|
1363
1377
|
_ts_param2(0, (0, import_nestjs_filter2.ApplyFilter)(RunFilter)),
|
|
@@ -1366,7 +1380,7 @@ _ts_decorate5([
|
|
|
1366
1380
|
typeof RunQueryDraft === "undefined" ? Object : RunQueryDraft
|
|
1367
1381
|
]),
|
|
1368
1382
|
_ts_metadata4("design:returntype", void 0)
|
|
1369
|
-
],
|
|
1383
|
+
], DurableApiControllerBase.prototype, "facets", null);
|
|
1370
1384
|
_ts_decorate5([
|
|
1371
1385
|
(0, import_common5.Get)("runs/values"),
|
|
1372
1386
|
_ts_param2(0, (0, import_common5.Query)()),
|
|
@@ -1375,20 +1389,20 @@ _ts_decorate5([
|
|
|
1375
1389
|
typeof Record === "undefined" ? Object : Record
|
|
1376
1390
|
]),
|
|
1377
1391
|
_ts_metadata4("design:returntype", void 0)
|
|
1378
|
-
],
|
|
1392
|
+
], DurableApiControllerBase.prototype, "values", null);
|
|
1379
1393
|
_ts_decorate5([
|
|
1380
1394
|
(0, import_common5.Get)("metrics"),
|
|
1381
1395
|
(0, import_common5.Header)("Content-Type", "text/plain; version=0.0.4"),
|
|
1382
1396
|
_ts_metadata4("design:type", Function),
|
|
1383
1397
|
_ts_metadata4("design:paramtypes", []),
|
|
1384
1398
|
_ts_metadata4("design:returntype", void 0)
|
|
1385
|
-
],
|
|
1399
|
+
], DurableApiControllerBase.prototype, "metrics", null);
|
|
1386
1400
|
_ts_decorate5([
|
|
1387
1401
|
(0, import_common5.Get)("workers"),
|
|
1388
1402
|
_ts_metadata4("design:type", Function),
|
|
1389
1403
|
_ts_metadata4("design:paramtypes", []),
|
|
1390
1404
|
_ts_metadata4("design:returntype", void 0)
|
|
1391
|
-
],
|
|
1405
|
+
], DurableApiControllerBase.prototype, "workers", null);
|
|
1392
1406
|
_ts_decorate5([
|
|
1393
1407
|
(0, import_common5.Get)("schedules"),
|
|
1394
1408
|
_ts_param2(0, (0, import_common5.Query)("namespace")),
|
|
@@ -1405,7 +1419,7 @@ _ts_decorate5([
|
|
|
1405
1419
|
String
|
|
1406
1420
|
]),
|
|
1407
1421
|
_ts_metadata4("design:returntype", void 0)
|
|
1408
|
-
],
|
|
1422
|
+
], DurableApiControllerBase.prototype, "schedules", null);
|
|
1409
1423
|
_ts_decorate5([
|
|
1410
1424
|
(0, import_common5.Post)("schedules/:id/pause"),
|
|
1411
1425
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1414,7 +1428,7 @@ _ts_decorate5([
|
|
|
1414
1428
|
String
|
|
1415
1429
|
]),
|
|
1416
1430
|
_ts_metadata4("design:returntype", void 0)
|
|
1417
|
-
],
|
|
1431
|
+
], DurableApiControllerBase.prototype, "pauseSchedule", null);
|
|
1418
1432
|
_ts_decorate5([
|
|
1419
1433
|
(0, import_common5.Post)("schedules/:id/resume"),
|
|
1420
1434
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1423,7 +1437,7 @@ _ts_decorate5([
|
|
|
1423
1437
|
String
|
|
1424
1438
|
]),
|
|
1425
1439
|
_ts_metadata4("design:returntype", void 0)
|
|
1426
|
-
],
|
|
1440
|
+
], DurableApiControllerBase.prototype, "resumeSchedule", null);
|
|
1427
1441
|
_ts_decorate5([
|
|
1428
1442
|
(0, import_common5.Post)("schedules/:id/trigger"),
|
|
1429
1443
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1432,13 +1446,22 @@ _ts_decorate5([
|
|
|
1432
1446
|
String
|
|
1433
1447
|
]),
|
|
1434
1448
|
_ts_metadata4("design:returntype", void 0)
|
|
1435
|
-
],
|
|
1449
|
+
], DurableApiControllerBase.prototype, "triggerSchedule", null);
|
|
1450
|
+
_ts_decorate5([
|
|
1451
|
+
(0, import_common5.Get)("workflows/:name/lifecycle"),
|
|
1452
|
+
_ts_param2(0, (0, import_common5.Param)("name")),
|
|
1453
|
+
_ts_metadata4("design:type", Function),
|
|
1454
|
+
_ts_metadata4("design:paramtypes", [
|
|
1455
|
+
String
|
|
1456
|
+
]),
|
|
1457
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1458
|
+
], DurableApiControllerBase.prototype, "workflowLifecycle", null);
|
|
1436
1459
|
_ts_decorate5([
|
|
1437
1460
|
(0, import_common5.Get)("topology"),
|
|
1438
1461
|
_ts_metadata4("design:type", Function),
|
|
1439
1462
|
_ts_metadata4("design:paramtypes", []),
|
|
1440
1463
|
_ts_metadata4("design:returntype", void 0)
|
|
1441
|
-
],
|
|
1464
|
+
], DurableApiControllerBase.prototype, "topology", null);
|
|
1442
1465
|
_ts_decorate5([
|
|
1443
1466
|
(0, import_common5.Get)("runs/:id"),
|
|
1444
1467
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1455,7 +1478,7 @@ _ts_decorate5([
|
|
|
1455
1478
|
Object
|
|
1456
1479
|
]),
|
|
1457
1480
|
_ts_metadata4("design:returntype", Promise)
|
|
1458
|
-
],
|
|
1481
|
+
], DurableApiControllerBase.prototype, "run", null);
|
|
1459
1482
|
_ts_decorate5([
|
|
1460
1483
|
(0, import_common5.Get)("runs/:id/fans/:group"),
|
|
1461
1484
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1478,7 +1501,7 @@ _ts_decorate5([
|
|
|
1478
1501
|
Object
|
|
1479
1502
|
]),
|
|
1480
1503
|
_ts_metadata4("design:returntype", Promise)
|
|
1481
|
-
],
|
|
1504
|
+
], DurableApiControllerBase.prototype, "fanMembers", null);
|
|
1482
1505
|
_ts_decorate5([
|
|
1483
1506
|
(0, import_common5.Sse)("runs/:id/stream"),
|
|
1484
1507
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1487,7 +1510,7 @@ _ts_decorate5([
|
|
|
1487
1510
|
String
|
|
1488
1511
|
]),
|
|
1489
1512
|
_ts_metadata4("design:returntype", void 0)
|
|
1490
|
-
],
|
|
1513
|
+
], DurableApiControllerBase.prototype, "stream", null);
|
|
1491
1514
|
_ts_decorate5([
|
|
1492
1515
|
(0, import_common5.Post)("runs/:id/retry"),
|
|
1493
1516
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1496,7 +1519,7 @@ _ts_decorate5([
|
|
|
1496
1519
|
String
|
|
1497
1520
|
]),
|
|
1498
1521
|
_ts_metadata4("design:returntype", void 0)
|
|
1499
|
-
],
|
|
1522
|
+
], DurableApiControllerBase.prototype, "retry", null);
|
|
1500
1523
|
_ts_decorate5([
|
|
1501
1524
|
(0, import_common5.Post)("runs/:id/retry-with-input"),
|
|
1502
1525
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1507,7 +1530,7 @@ _ts_decorate5([
|
|
|
1507
1530
|
Object
|
|
1508
1531
|
]),
|
|
1509
1532
|
_ts_metadata4("design:returntype", void 0)
|
|
1510
|
-
],
|
|
1533
|
+
], DurableApiControllerBase.prototype, "retryWithInput", null);
|
|
1511
1534
|
_ts_decorate5([
|
|
1512
1535
|
(0, import_common5.Post)("bulk/:action"),
|
|
1513
1536
|
_ts_param2(0, (0, import_common5.Param)("action")),
|
|
@@ -1520,7 +1543,7 @@ _ts_decorate5([
|
|
|
1520
1543
|
String
|
|
1521
1544
|
]),
|
|
1522
1545
|
_ts_metadata4("design:returntype", void 0)
|
|
1523
|
-
],
|
|
1546
|
+
], DurableApiControllerBase.prototype, "bulk", null);
|
|
1524
1547
|
_ts_decorate5([
|
|
1525
1548
|
(0, import_common5.Post)("runs/:id/cancel"),
|
|
1526
1549
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1531,7 +1554,18 @@ _ts_decorate5([
|
|
|
1531
1554
|
String
|
|
1532
1555
|
]),
|
|
1533
1556
|
_ts_metadata4("design:returntype", Promise)
|
|
1534
|
-
],
|
|
1557
|
+
], DurableApiControllerBase.prototype, "cancel", null);
|
|
1558
|
+
_ts_decorate5([
|
|
1559
|
+
(0, import_common5.Post)("runs/:id/republish-lifecycle"),
|
|
1560
|
+
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
1561
|
+
_ts_param2(1, (0, import_common5.Body)()),
|
|
1562
|
+
_ts_metadata4("design:type", Function),
|
|
1563
|
+
_ts_metadata4("design:paramtypes", [
|
|
1564
|
+
String,
|
|
1565
|
+
Object
|
|
1566
|
+
]),
|
|
1567
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1568
|
+
], DurableApiControllerBase.prototype, "republishLifecycle", null);
|
|
1535
1569
|
_ts_decorate5([
|
|
1536
1570
|
(0, import_common5.Post)("runs/:id/continue"),
|
|
1537
1571
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1540,7 +1574,7 @@ _ts_decorate5([
|
|
|
1540
1574
|
String
|
|
1541
1575
|
]),
|
|
1542
1576
|
_ts_metadata4("design:returntype", Promise)
|
|
1543
|
-
],
|
|
1577
|
+
], DurableApiControllerBase.prototype, "continue", null);
|
|
1544
1578
|
_ts_decorate5([
|
|
1545
1579
|
(0, import_common5.Post)("runs/:id/redispatch"),
|
|
1546
1580
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1549,7 +1583,7 @@ _ts_decorate5([
|
|
|
1549
1583
|
String
|
|
1550
1584
|
]),
|
|
1551
1585
|
_ts_metadata4("design:returntype", Promise)
|
|
1552
|
-
],
|
|
1586
|
+
], DurableApiControllerBase.prototype, "redispatch", null);
|
|
1553
1587
|
_ts_decorate5([
|
|
1554
1588
|
(0, import_common5.Post)("webhooks/:token"),
|
|
1555
1589
|
_ts_param2(0, (0, import_common5.Param)("token")),
|
|
@@ -1560,7 +1594,7 @@ _ts_decorate5([
|
|
|
1560
1594
|
Object
|
|
1561
1595
|
]),
|
|
1562
1596
|
_ts_metadata4("design:returntype", Promise)
|
|
1563
|
-
],
|
|
1597
|
+
], DurableApiControllerBase.prototype, "webhook", null);
|
|
1564
1598
|
_ts_decorate5([
|
|
1565
1599
|
(0, import_common5.Get)("runs/:id/events/:key"),
|
|
1566
1600
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1571,7 +1605,7 @@ _ts_decorate5([
|
|
|
1571
1605
|
String
|
|
1572
1606
|
]),
|
|
1573
1607
|
_ts_metadata4("design:returntype", void 0)
|
|
1574
|
-
],
|
|
1608
|
+
], DurableApiControllerBase.prototype, "event", null);
|
|
1575
1609
|
_ts_decorate5([
|
|
1576
1610
|
(0, import_common5.Post)("runs/:id/updates/:name"),
|
|
1577
1611
|
_ts_param2(0, (0, import_common5.Param)("id")),
|
|
@@ -1584,8 +1618,8 @@ _ts_decorate5([
|
|
|
1584
1618
|
Object
|
|
1585
1619
|
]),
|
|
1586
1620
|
_ts_metadata4("design:returntype", void 0)
|
|
1587
|
-
],
|
|
1588
|
-
|
|
1621
|
+
], DurableApiControllerBase.prototype, "update", null);
|
|
1622
|
+
DurableApiControllerBase = _ts_decorate5([
|
|
1589
1623
|
(0, import_common5.Controller)(),
|
|
1590
1624
|
(0, import_common5.UseInterceptors)(import_nestjs_filter2.ApplyFilterInterceptor),
|
|
1591
1625
|
(0, import_common5.UseFilters)(NotModifiedFilter),
|
|
@@ -1594,7 +1628,7 @@ DurableApiController = _ts_decorate5([
|
|
|
1594
1628
|
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
1595
1629
|
typeof import_nestjs_filter2.FilterRunner === "undefined" ? Object : import_nestjs_filter2.FilterRunner
|
|
1596
1630
|
])
|
|
1597
|
-
],
|
|
1631
|
+
], DurableApiControllerBase);
|
|
1598
1632
|
function notFound(error) {
|
|
1599
1633
|
if (error instanceof Error && error.name === "ScheduleNotFoundError") {
|
|
1600
1634
|
throw new import_common5.NotFoundException(error.message);
|
|
@@ -1602,497 +1636,58 @@ function notFound(error) {
|
|
|
1602
1636
|
throw error;
|
|
1603
1637
|
}
|
|
1604
1638
|
__name(notFound, "notFound");
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
// src/server/auth/dashboard-auth-config.ts
|
|
1610
|
-
var DASHBOARD_AUTH = Symbol("DASHBOARD_AUTH");
|
|
1611
|
-
var DEFAULT_TTL = "8h";
|
|
1612
|
-
var DEFAULT_TTL_MS = 8 * 60 * 60 * 1e3;
|
|
1613
|
-
var DURATION_UNITS = {
|
|
1614
|
-
s: 1e3,
|
|
1615
|
-
m: 60 * 1e3,
|
|
1616
|
-
h: 60 * 60 * 1e3,
|
|
1617
|
-
d: 24 * 60 * 60 * 1e3
|
|
1618
|
-
};
|
|
1619
|
-
function durationToMs(ttl) {
|
|
1620
|
-
const match = /^(\d+)([smhd])$/.exec(ttl.trim());
|
|
1621
|
-
if (!match) return DEFAULT_TTL_MS;
|
|
1622
|
-
const unit = DURATION_UNITS[match[2] ?? ""];
|
|
1623
|
-
if (unit === void 0) return DEFAULT_TTL_MS;
|
|
1624
|
-
return Number(match[1]) * unit;
|
|
1625
|
-
}
|
|
1626
|
-
__name(durationToMs, "durationToMs");
|
|
1627
|
-
function resolveDashboardAuth(options) {
|
|
1628
|
-
if (options === void 0) return null;
|
|
1629
|
-
if (typeof options.secret !== "string" || options.secret === "") {
|
|
1630
|
-
throw new Error("DurableDashboardModule: dashboardAuth.secret is required and must be a non-empty string (HMAC-SHA256 signing key, 32+ bytes recommended). Failing closed.");
|
|
1631
|
-
}
|
|
1632
|
-
const modes = [];
|
|
1633
|
-
if (options.session !== void 0) {
|
|
1634
|
-
if (typeof options.session !== "function") {
|
|
1635
|
-
throw new Error("DurableDashboardModule: dashboardAuth.session must be a function.");
|
|
1636
|
-
}
|
|
1637
|
-
modes.push("session");
|
|
1638
|
-
}
|
|
1639
|
-
if (options.login !== void 0) {
|
|
1640
|
-
if (typeof options.login !== "function") {
|
|
1641
|
-
throw new Error("DurableDashboardModule: dashboardAuth.login must be a function.");
|
|
1642
|
-
}
|
|
1643
|
-
modes.push("login");
|
|
1644
|
-
}
|
|
1645
|
-
if (options.revalidate !== void 0 && typeof options.revalidate !== "function") {
|
|
1646
|
-
throw new Error("DurableDashboardModule: dashboardAuth.revalidate must be a function.");
|
|
1639
|
+
function notSupportedByServer(error) {
|
|
1640
|
+
if (error?.code === "unsupported-request") {
|
|
1641
|
+
throw new import_common5.NotImplementedException(error instanceof Error ? error.message : String(error));
|
|
1647
1642
|
}
|
|
1648
|
-
|
|
1649
|
-
throw new Error("DurableDashboardModule: dashboardAuth.unauthenticatedPage must be a function.");
|
|
1650
|
-
}
|
|
1651
|
-
if (modes.length === 0) {
|
|
1652
|
-
throw new Error("DurableDashboardModule: dashboardAuth needs at least one of `session` or `login` (otherwise the cookie can never be minted). Failing closed.");
|
|
1653
|
-
}
|
|
1654
|
-
return {
|
|
1655
|
-
secret: options.secret,
|
|
1656
|
-
ttlMs: durationToMs(options.ttl ?? DEFAULT_TTL),
|
|
1657
|
-
modes,
|
|
1658
|
-
...options.session !== void 0 ? {
|
|
1659
|
-
session: options.session
|
|
1660
|
-
} : {},
|
|
1661
|
-
...options.login !== void 0 ? {
|
|
1662
|
-
login: options.login
|
|
1663
|
-
} : {},
|
|
1664
|
-
...options.revalidate !== void 0 ? {
|
|
1665
|
-
revalidate: options.revalidate
|
|
1666
|
-
} : {},
|
|
1667
|
-
...options.unauthenticatedPage !== void 0 ? {
|
|
1668
|
-
unauthenticatedPage: options.unauthenticatedPage
|
|
1669
|
-
} : {}
|
|
1670
|
-
};
|
|
1671
|
-
}
|
|
1672
|
-
__name(resolveDashboardAuth, "resolveDashboardAuth");
|
|
1673
|
-
|
|
1674
|
-
// src/server/auth/login-page.ts
|
|
1675
|
-
function page(content, title = "Durable") {
|
|
1676
|
-
return `<!doctype html>
|
|
1677
|
-
<html lang="en">
|
|
1678
|
-
<head>
|
|
1679
|
-
<meta charset="utf-8" />
|
|
1680
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1681
|
-
<meta name="robots" content="noindex, nofollow" />
|
|
1682
|
-
<title>${title}</title>
|
|
1683
|
-
<style>
|
|
1684
|
-
:root { color-scheme: dark; }
|
|
1685
|
-
* { box-sizing: border-box; }
|
|
1686
|
-
body {
|
|
1687
|
-
margin: 0;
|
|
1688
|
-
min-height: 100vh;
|
|
1689
|
-
display: flex;
|
|
1690
|
-
align-items: center;
|
|
1691
|
-
justify-content: center;
|
|
1692
|
-
background: #09090b;
|
|
1693
|
-
color: #e4e4e7;
|
|
1694
|
-
font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1695
|
-
padding: 16px;
|
|
1696
|
-
}
|
|
1697
|
-
.card {
|
|
1698
|
-
width: 100%;
|
|
1699
|
-
max-width: 384px;
|
|
1700
|
-
border: 1px solid #27272a;
|
|
1701
|
-
background: #18181b;
|
|
1702
|
-
border-radius: 8px;
|
|
1703
|
-
padding: 32px;
|
|
1704
|
-
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
|
|
1705
|
-
}
|
|
1706
|
-
.brand {
|
|
1707
|
-
margin: 0 0 24px;
|
|
1708
|
-
text-align: center;
|
|
1709
|
-
font-size: 18px;
|
|
1710
|
-
font-weight: 600;
|
|
1711
|
-
color: #34d399;
|
|
1712
|
-
}
|
|
1713
|
-
h1 {
|
|
1714
|
-
margin: 0 0 12px;
|
|
1715
|
-
font-size: 16px;
|
|
1716
|
-
font-weight: 600;
|
|
1717
|
-
color: #f4f4f5;
|
|
1718
|
-
}
|
|
1719
|
-
p { margin: 0 0 16px; color: #a1a1aa; }
|
|
1720
|
-
form { display: flex; flex-direction: column; gap: 16px; }
|
|
1721
|
-
label { display: flex; flex-direction: column; gap: 6px; }
|
|
1722
|
-
.field-label {
|
|
1723
|
-
font-size: 11px;
|
|
1724
|
-
text-transform: uppercase;
|
|
1725
|
-
letter-spacing: 0.05em;
|
|
1726
|
-
color: #71717a;
|
|
1727
|
-
}
|
|
1728
|
-
input {
|
|
1729
|
-
border-radius: 4px;
|
|
1730
|
-
border: 1px solid #3f3f46;
|
|
1731
|
-
background: #09090b;
|
|
1732
|
-
color: #f4f4f5;
|
|
1733
|
-
padding: 8px 12px;
|
|
1734
|
-
font: inherit;
|
|
1735
|
-
outline: none;
|
|
1736
|
-
}
|
|
1737
|
-
input:focus { border-color: rgb(52 211 153 / 0.6); }
|
|
1738
|
-
#error {
|
|
1739
|
-
display: none;
|
|
1740
|
-
margin: 0;
|
|
1741
|
-
font-size: 12px;
|
|
1742
|
-
color: #fb7185;
|
|
1743
|
-
}
|
|
1744
|
-
button, .button {
|
|
1745
|
-
margin-top: 8px;
|
|
1746
|
-
border-radius: 4px;
|
|
1747
|
-
border: 1px solid rgb(52 211 153 / 0.4);
|
|
1748
|
-
background: rgb(52 211 153 / 0.1);
|
|
1749
|
-
color: #6ee7b7;
|
|
1750
|
-
padding: 8px 12px;
|
|
1751
|
-
font: inherit;
|
|
1752
|
-
font-size: 12px;
|
|
1753
|
-
font-weight: 500;
|
|
1754
|
-
text-transform: uppercase;
|
|
1755
|
-
letter-spacing: 0.05em;
|
|
1756
|
-
cursor: pointer;
|
|
1757
|
-
display: inline-block;
|
|
1758
|
-
text-align: center;
|
|
1759
|
-
text-decoration: none;
|
|
1760
|
-
box-sizing: border-box;
|
|
1761
|
-
}
|
|
1762
|
-
button:hover:not(:disabled), .button:hover { background: rgb(52 211 153 / 0.2); }
|
|
1763
|
-
button:disabled { opacity: 0.6; cursor: default; }
|
|
1764
|
-
</style>
|
|
1765
|
-
</head>
|
|
1766
|
-
<body>
|
|
1767
|
-
<div class="card">
|
|
1768
|
-
${content}
|
|
1769
|
-
</div>
|
|
1770
|
-
</body>
|
|
1771
|
-
</html>`;
|
|
1643
|
+
throw error;
|
|
1772
1644
|
}
|
|
1773
|
-
__name(
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
return page(`<p class="brand">Durable</p>
|
|
1778
|
-
<form id="login-form" autocomplete="on">
|
|
1779
|
-
<label>
|
|
1780
|
-
<span class="field-label">Username</span>
|
|
1781
|
-
<input id="username" name="username" type="text" autocomplete="username" required autofocus />
|
|
1782
|
-
</label>
|
|
1783
|
-
<label>
|
|
1784
|
-
<span class="field-label">Password</span>
|
|
1785
|
-
<input id="password" name="password" type="password" autocomplete="current-password" />
|
|
1786
|
-
</label>
|
|
1787
|
-
<p id="error" role="alert">Invalid username or password.</p>
|
|
1788
|
-
<button id="submit" type="submit">Sign in</button>
|
|
1789
|
-
</form>
|
|
1790
|
-
<script>
|
|
1791
|
-
(function () {
|
|
1792
|
-
var LOGIN_ACTION = ${JSON.stringify(loginAction)};
|
|
1793
|
-
var DEFAULT_RETURN_TO = ${JSON.stringify(defaultReturnTo)};
|
|
1794
|
-
var params = new URLSearchParams(window.location.search);
|
|
1795
|
-
var errorBox = document.getElementById('error');
|
|
1796
|
-
if (params.get('error')) errorBox.style.display = 'block';
|
|
1797
|
-
|
|
1798
|
-
function sameOriginReturnTo(value) {
|
|
1799
|
-
if (typeof value !== 'string' || value === '') return DEFAULT_RETURN_TO;
|
|
1800
|
-
if (value.charAt(0) !== '/' || value.charAt(1) === '/' || value.indexOf('://') !== -1) {
|
|
1801
|
-
return DEFAULT_RETURN_TO;
|
|
1802
|
-
}
|
|
1803
|
-
return value;
|
|
1645
|
+
__name(notSupportedByServer, "notSupportedByServer");
|
|
1646
|
+
var DurableApiController = class extends DurableApiControllerBase {
|
|
1647
|
+
static {
|
|
1648
|
+
__name(this, "DurableApiController");
|
|
1804
1649
|
}
|
|
1650
|
+
};
|
|
1651
|
+
DurableApiController = _ts_decorate5([
|
|
1652
|
+
(0, import_common5.Controller)()
|
|
1653
|
+
], DurableApiController);
|
|
1805
1654
|
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
errorBox.style.display = 'none';
|
|
1812
|
-
var returnTo = sameOriginReturnTo(params.get('returnTo'));
|
|
1813
|
-
fetch(LOGIN_ACTION, {
|
|
1814
|
-
method: 'POST',
|
|
1815
|
-
headers: { 'content-type': 'application/json' },
|
|
1816
|
-
credentials: 'same-origin',
|
|
1817
|
-
body: JSON.stringify({
|
|
1818
|
-
username: document.getElementById('username').value,
|
|
1819
|
-
password: document.getElementById('password').value,
|
|
1820
|
-
returnTo: returnTo,
|
|
1821
|
-
}),
|
|
1822
|
-
})
|
|
1823
|
-
.then(function (response) {
|
|
1824
|
-
if (!response.ok) throw new Error('unauthorized');
|
|
1825
|
-
return response.json();
|
|
1826
|
-
})
|
|
1827
|
-
.then(function (data) {
|
|
1828
|
-
window.location.href = data.redirectTo || DEFAULT_RETURN_TO;
|
|
1829
|
-
})
|
|
1830
|
-
.catch(function () {
|
|
1831
|
-
errorBox.style.display = 'block';
|
|
1832
|
-
submitButton.disabled = false;
|
|
1833
|
-
});
|
|
1834
|
-
});
|
|
1835
|
-
})();
|
|
1836
|
-
</script>`, "Sign in \u2014 Durable");
|
|
1837
|
-
}
|
|
1838
|
-
__name(renderLoginPage, "renderLoginPage");
|
|
1839
|
-
function renderSessionRequiredPage(basePath) {
|
|
1840
|
-
return page(`<h1>Open this console from your application</h1>
|
|
1841
|
-
<p>Your session is minted by the host app. Use its console launcher to sign in, then reload.</p>
|
|
1842
|
-
<a class="button" href="${basePath}">Retry</a>`);
|
|
1843
|
-
}
|
|
1844
|
-
__name(renderSessionRequiredPage, "renderSessionRequiredPage");
|
|
1845
|
-
|
|
1846
|
-
// src/server/auth/request.ts
|
|
1847
|
-
function isRecord2(value) {
|
|
1848
|
-
return typeof value === "object" && value !== null;
|
|
1849
|
-
}
|
|
1850
|
-
__name(isRecord2, "isRecord");
|
|
1851
|
-
function readHeaders(request) {
|
|
1852
|
-
if (!isRecord2(request)) return {};
|
|
1853
|
-
const headers = request.headers;
|
|
1854
|
-
return isRecord2(headers) ? headers : {};
|
|
1855
|
-
}
|
|
1856
|
-
__name(readHeaders, "readHeaders");
|
|
1857
|
-
function headerToString(value) {
|
|
1858
|
-
if (typeof value === "string") return value;
|
|
1859
|
-
if (Array.isArray(value) && value.every((part) => typeof part === "string")) {
|
|
1860
|
-
return value.join(",");
|
|
1861
|
-
}
|
|
1862
|
-
return void 0;
|
|
1863
|
-
}
|
|
1864
|
-
__name(headerToString, "headerToString");
|
|
1865
|
-
function readCookieHeader(request) {
|
|
1866
|
-
return headerToString(readHeaders(request).cookie);
|
|
1867
|
-
}
|
|
1868
|
-
__name(readCookieHeader, "readCookieHeader");
|
|
1869
|
-
function isHttpsRequest(request) {
|
|
1870
|
-
if (isRecord2(request) && request.protocol === "https") return true;
|
|
1871
|
-
const forwarded = headerToString(readHeaders(request)["x-forwarded-proto"]);
|
|
1872
|
-
if (forwarded === void 0) return false;
|
|
1873
|
-
return forwarded.split(",").map((proto) => proto.trim().toLowerCase()).includes("https");
|
|
1874
|
-
}
|
|
1875
|
-
__name(isHttpsRequest, "isHttpsRequest");
|
|
1876
|
-
function originalRequestUrl(request) {
|
|
1877
|
-
if (!isRecord2(request)) return "/";
|
|
1878
|
-
if (typeof request.originalUrl === "string" && request.originalUrl !== "") {
|
|
1879
|
-
return request.originalUrl;
|
|
1880
|
-
}
|
|
1881
|
-
if (typeof request.url === "string" && request.url !== "") return request.url;
|
|
1882
|
-
return "/";
|
|
1883
|
-
}
|
|
1884
|
-
__name(originalRequestUrl, "originalRequestUrl");
|
|
1885
|
-
function sanitizeReturnTo(candidate, fallback) {
|
|
1886
|
-
if (typeof candidate !== "string") return fallback;
|
|
1887
|
-
if (!candidate.startsWith("/")) return fallback;
|
|
1888
|
-
if (candidate.startsWith("//")) return fallback;
|
|
1889
|
-
if (candidate.includes("://")) return fallback;
|
|
1890
|
-
return candidate;
|
|
1891
|
-
}
|
|
1892
|
-
__name(sanitizeReturnTo, "sanitizeReturnTo");
|
|
1655
|
+
// src/server/durable-dashboard.module.ts
|
|
1656
|
+
var import_reflect_metadata2 = require("reflect-metadata");
|
|
1657
|
+
var import_nestjs_filter3 = require("@dudousxd/nestjs-filter");
|
|
1658
|
+
var import_common7 = require("@nestjs/common");
|
|
1659
|
+
var import_core = require("@nestjs/core");
|
|
1893
1660
|
|
|
1894
|
-
// src/server/
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
}
|
|
1907
|
-
if (name in cookies) continue;
|
|
1908
|
-
try {
|
|
1909
|
-
cookies[name] = decodeURIComponent(rawValue);
|
|
1910
|
-
} catch {
|
|
1911
|
-
cookies[name] = rawValue;
|
|
1661
|
+
// src/server/controller-decorators.ts
|
|
1662
|
+
var import_reflect_metadata = require("reflect-metadata");
|
|
1663
|
+
var CAN_ANYONE_METADATA = "authorization:can-anyone";
|
|
1664
|
+
function markOpenToAuthorization(controller) {
|
|
1665
|
+
Reflect.defineMetadata(CAN_ANYONE_METADATA, true, controller);
|
|
1666
|
+
}
|
|
1667
|
+
__name(markOpenToAuthorization, "markOpenToAuthorization");
|
|
1668
|
+
function controllerFor(base, decorators) {
|
|
1669
|
+
if (decorators === void 0 || decorators.length === 0) return base;
|
|
1670
|
+
const derived = class extends base {
|
|
1671
|
+
static {
|
|
1672
|
+
__name(this, "derived");
|
|
1912
1673
|
}
|
|
1913
|
-
}
|
|
1914
|
-
return cookies;
|
|
1915
|
-
}
|
|
1916
|
-
__name(parseCookieHeader, "parseCookieHeader");
|
|
1917
|
-
function serializeSetCookie(name, value, options) {
|
|
1918
|
-
const parts = [
|
|
1919
|
-
`${name}=${options.clear ? "" : encodeURIComponent(value)}`
|
|
1920
|
-
];
|
|
1921
|
-
parts.push(`Path=${options.path}`);
|
|
1922
|
-
parts.push("HttpOnly");
|
|
1923
|
-
parts.push("SameSite=Lax");
|
|
1924
|
-
if (options.secure) parts.push("Secure");
|
|
1925
|
-
if (options.clear) {
|
|
1926
|
-
parts.push("Max-Age=0");
|
|
1927
|
-
parts.push("Expires=Thu, 01 Jan 1970 00:00:00 GMT");
|
|
1928
|
-
} else {
|
|
1929
|
-
parts.push(`Max-Age=${options.maxAgeSeconds}`);
|
|
1930
|
-
}
|
|
1931
|
-
return parts.join("; ");
|
|
1932
|
-
}
|
|
1933
|
-
__name(serializeSetCookie, "serializeSetCookie");
|
|
1934
|
-
|
|
1935
|
-
// src/server/auth/session-cookie.ts
|
|
1936
|
-
var import_node_crypto = require("crypto");
|
|
1937
|
-
var EXP_GRACE_MS = 3e4;
|
|
1938
|
-
function base64urlEncode(value) {
|
|
1939
|
-
return Buffer.from(value, "utf8").toString("base64url");
|
|
1940
|
-
}
|
|
1941
|
-
__name(base64urlEncode, "base64urlEncode");
|
|
1942
|
-
function base64urlDecode(value) {
|
|
1943
|
-
return Buffer.from(value, "base64url").toString("utf8");
|
|
1944
|
-
}
|
|
1945
|
-
__name(base64urlDecode, "base64urlDecode");
|
|
1946
|
-
function hmac(secret, payload) {
|
|
1947
|
-
return (0, import_node_crypto.createHmac)("sha256", secret).update(payload).digest("base64url");
|
|
1948
|
-
}
|
|
1949
|
-
__name(hmac, "hmac");
|
|
1950
|
-
function signSessionCookie(user, options) {
|
|
1951
|
-
const issuedAt = options.now ?? Date.now();
|
|
1952
|
-
const session = {
|
|
1953
|
-
sub: user.id,
|
|
1954
|
-
...user.name !== void 0 ? {
|
|
1955
|
-
name: user.name
|
|
1956
|
-
} : {},
|
|
1957
|
-
roles: user.roles ?? [],
|
|
1958
|
-
iat: issuedAt,
|
|
1959
|
-
exp: issuedAt + options.ttlMs
|
|
1960
|
-
};
|
|
1961
|
-
const encodedPayload = base64urlEncode(JSON.stringify(session));
|
|
1962
|
-
const signature = hmac(options.secret, encodedPayload);
|
|
1963
|
-
return `${encodedPayload}.${signature}`;
|
|
1964
|
-
}
|
|
1965
|
-
__name(signSessionCookie, "signSessionCookie");
|
|
1966
|
-
function isSessionPayload(value) {
|
|
1967
|
-
if (typeof value !== "object" || value === null) return false;
|
|
1968
|
-
const record = {
|
|
1969
|
-
...value
|
|
1970
1674
|
};
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
if (!Array.isArray(record.roles)) return false;
|
|
1974
|
-
if (!record.roles.every((role) => typeof role === "string")) return false;
|
|
1975
|
-
if (typeof record.iat !== "number" || !Number.isFinite(record.iat)) return false;
|
|
1976
|
-
if (typeof record.exp !== "number" || !Number.isFinite(record.exp)) return false;
|
|
1977
|
-
return true;
|
|
1978
|
-
}
|
|
1979
|
-
__name(isSessionPayload, "isSessionPayload");
|
|
1980
|
-
function verifySessionCookie(value, options) {
|
|
1981
|
-
try {
|
|
1982
|
-
const dot = value.indexOf(".");
|
|
1983
|
-
if (dot <= 0 || dot === value.length - 1) return null;
|
|
1984
|
-
const encodedPayload = value.slice(0, dot);
|
|
1985
|
-
const providedSignature = value.slice(dot + 1);
|
|
1986
|
-
const expectedSignature = hmac(options.secret, encodedPayload);
|
|
1987
|
-
const provided = Buffer.from(providedSignature, "base64url");
|
|
1988
|
-
const expected = Buffer.from(expectedSignature, "base64url");
|
|
1989
|
-
if (provided.length !== expected.length) return null;
|
|
1990
|
-
if (!(0, import_node_crypto.timingSafeEqual)(provided, expected)) return null;
|
|
1991
|
-
const decoded = JSON.parse(base64urlDecode(encodedPayload));
|
|
1992
|
-
if (!isSessionPayload(decoded)) return null;
|
|
1993
|
-
const now = options.now ?? Date.now();
|
|
1994
|
-
if (now > decoded.exp + EXP_GRACE_MS) return null;
|
|
1995
|
-
const session = {
|
|
1996
|
-
sub: decoded.sub,
|
|
1997
|
-
...decoded.name !== void 0 ? {
|
|
1998
|
-
name: decoded.name
|
|
1999
|
-
} : {},
|
|
2000
|
-
roles: decoded.roles,
|
|
2001
|
-
iat: decoded.iat,
|
|
2002
|
-
exp: decoded.exp
|
|
2003
|
-
};
|
|
2004
|
-
return session;
|
|
2005
|
-
} catch {
|
|
2006
|
-
return null;
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
__name(verifySessionCookie, "verifySessionCookie");
|
|
2010
|
-
|
|
2011
|
-
// src/server/auth/session-cookie-io.ts
|
|
2012
|
-
var SESSION_COOKIE_NAME = "durable_dashboard_session";
|
|
2013
|
-
var COOKIE_PATH = "/";
|
|
2014
|
-
function issueSessionCookie(user, context) {
|
|
2015
|
-
const value = signSessionCookie(user, {
|
|
2016
|
-
secret: context.auth.secret,
|
|
2017
|
-
ttlMs: context.auth.ttlMs,
|
|
2018
|
-
...context.now !== void 0 ? {
|
|
2019
|
-
now: context.now
|
|
2020
|
-
} : {}
|
|
2021
|
-
});
|
|
2022
|
-
const cookie = serializeSetCookie(SESSION_COOKIE_NAME, value, {
|
|
2023
|
-
path: COOKIE_PATH,
|
|
2024
|
-
maxAgeSeconds: Math.floor(context.auth.ttlMs / 1e3),
|
|
2025
|
-
secure: isHttpsRequest(context.request)
|
|
2026
|
-
});
|
|
2027
|
-
appendSetCookie(context.response, cookie);
|
|
2028
|
-
}
|
|
2029
|
-
__name(issueSessionCookie, "issueSessionCookie");
|
|
2030
|
-
function clearSessionCookie(context) {
|
|
2031
|
-
const cookie = serializeSetCookie(SESSION_COOKIE_NAME, "", {
|
|
2032
|
-
path: COOKIE_PATH,
|
|
2033
|
-
maxAgeSeconds: 0,
|
|
2034
|
-
secure: isHttpsRequest(context.request),
|
|
2035
|
-
clear: true
|
|
2036
|
-
});
|
|
2037
|
-
appendSetCookie(context.response, cookie);
|
|
2038
|
-
}
|
|
2039
|
-
__name(clearSessionCookie, "clearSessionCookie");
|
|
2040
|
-
function readSessionFromRequest(auth, request) {
|
|
2041
|
-
const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
|
|
2042
|
-
if (cookieValue === void 0) return null;
|
|
2043
|
-
return verifySessionCookie(cookieValue, {
|
|
2044
|
-
secret: auth.secret
|
|
1675
|
+
Object.defineProperty(derived, "name", {
|
|
1676
|
+
value: base.name
|
|
2045
1677
|
});
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
const revalidate = auth.revalidate;
|
|
2051
|
-
if (!revalidate) return Promise.resolve(true);
|
|
2052
|
-
const key = `${auth.secret}:${user.id}`;
|
|
2053
|
-
const inFlight = inFlightRevalidations.get(key);
|
|
2054
|
-
if (inFlight) return inFlight;
|
|
2055
|
-
const call = Promise.resolve().then(() => revalidate(user)).catch(() => false).finally(() => {
|
|
2056
|
-
inFlightRevalidations.delete(key);
|
|
2057
|
-
});
|
|
2058
|
-
inFlightRevalidations.set(key, call);
|
|
2059
|
-
return call;
|
|
2060
|
-
}
|
|
2061
|
-
__name(revalidateOnce, "revalidateOnce");
|
|
2062
|
-
async function maybeRenewSession(auth, session, request, response, now = Date.now()) {
|
|
2063
|
-
if (now - session.iat <= auth.ttlMs / 2) return true;
|
|
2064
|
-
const user = {
|
|
2065
|
-
id: session.sub,
|
|
2066
|
-
...session.name !== void 0 ? {
|
|
2067
|
-
name: session.name
|
|
2068
|
-
} : {},
|
|
2069
|
-
roles: session.roles
|
|
2070
|
-
};
|
|
2071
|
-
const allowed = await revalidateOnce(auth, user);
|
|
2072
|
-
if (!allowed) {
|
|
2073
|
-
clearSessionCookie({
|
|
2074
|
-
request,
|
|
2075
|
-
response
|
|
2076
|
-
});
|
|
2077
|
-
return false;
|
|
1678
|
+
markOpenToAuthorization(derived);
|
|
1679
|
+
let decorated = derived;
|
|
1680
|
+
for (const decorator of decorators) {
|
|
1681
|
+
decorated = decorator(decorated) ?? decorated;
|
|
2078
1682
|
}
|
|
2079
|
-
|
|
2080
|
-
auth,
|
|
2081
|
-
request,
|
|
2082
|
-
response,
|
|
2083
|
-
now
|
|
2084
|
-
});
|
|
2085
|
-
return true;
|
|
1683
|
+
return decorated;
|
|
2086
1684
|
}
|
|
2087
|
-
__name(
|
|
1685
|
+
__name(controllerFor, "controllerFor");
|
|
2088
1686
|
|
|
2089
1687
|
// src/server/durable-ui.controller.ts
|
|
2090
1688
|
var import_node_fs = require("fs");
|
|
2091
1689
|
var import_node_path = require("path");
|
|
2092
1690
|
var import_node_url = require("url");
|
|
2093
|
-
var import_common8 = require("@nestjs/common");
|
|
2094
|
-
|
|
2095
|
-
// src/server/auth/login-redirect.exception.ts
|
|
2096
1691
|
var import_common6 = require("@nestjs/common");
|
|
2097
1692
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
2098
1693
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -2108,46 +1703,6 @@ function _ts_decorate6(decorators, target, key, desc) {
|
|
|
2108
1703
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2109
1704
|
}
|
|
2110
1705
|
__name(_ts_decorate6, "_ts_decorate");
|
|
2111
|
-
var DashboardLoginRedirectException = class extends import_common6.HttpException {
|
|
2112
|
-
static {
|
|
2113
|
-
__name(this, "DashboardLoginRedirectException");
|
|
2114
|
-
}
|
|
2115
|
-
location;
|
|
2116
|
-
constructor(location) {
|
|
2117
|
-
super({
|
|
2118
|
-
location
|
|
2119
|
-
}, import_common6.HttpStatus.FOUND), this.location = location;
|
|
2120
|
-
}
|
|
2121
|
-
};
|
|
2122
|
-
var DashboardLoginRedirectFilter = class {
|
|
2123
|
-
static {
|
|
2124
|
-
__name(this, "DashboardLoginRedirectFilter");
|
|
2125
|
-
}
|
|
2126
|
-
catch(exception, host) {
|
|
2127
|
-
const response = host.switchToHttp().getResponse();
|
|
2128
|
-
redirectRaw(response, exception.location);
|
|
2129
|
-
}
|
|
2130
|
-
};
|
|
2131
|
-
DashboardLoginRedirectFilter = _ts_decorate6([
|
|
2132
|
-
(0, import_common6.Catch)(DashboardLoginRedirectException)
|
|
2133
|
-
], DashboardLoginRedirectFilter);
|
|
2134
|
-
|
|
2135
|
-
// src/server/auth/session-required.exception.ts
|
|
2136
|
-
var import_common7 = require("@nestjs/common");
|
|
2137
|
-
function _ts_decorate7(decorators, target, key, desc) {
|
|
2138
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2139
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2140
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2141
|
-
} else {
|
|
2142
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2143
|
-
if (d = decorators[i]) {
|
|
2144
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2149
|
-
}
|
|
2150
|
-
__name(_ts_decorate7, "_ts_decorate");
|
|
2151
1706
|
function _ts_metadata5(metadataKey, metadataValue) {
|
|
2152
1707
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2153
1708
|
return Reflect.metadata(metadataKey, metadataValue);
|
|
@@ -2160,91 +1715,6 @@ function _ts_param3(paramIndex, decorator) {
|
|
|
2160
1715
|
};
|
|
2161
1716
|
}
|
|
2162
1717
|
__name(_ts_param3, "_ts_param");
|
|
2163
|
-
var DashboardSessionRequiredException = class extends import_common7.HttpException {
|
|
2164
|
-
static {
|
|
2165
|
-
__name(this, "DashboardSessionRequiredException");
|
|
2166
|
-
}
|
|
2167
|
-
basePath;
|
|
2168
|
-
constructor(basePath) {
|
|
2169
|
-
super({
|
|
2170
|
-
basePath
|
|
2171
|
-
}, import_common7.HttpStatus.UNAUTHORIZED), this.basePath = basePath;
|
|
2172
|
-
}
|
|
2173
|
-
};
|
|
2174
|
-
var DashboardSessionRequiredFilter = class _DashboardSessionRequiredFilter {
|
|
2175
|
-
static {
|
|
2176
|
-
__name(this, "DashboardSessionRequiredFilter");
|
|
2177
|
-
}
|
|
2178
|
-
auth;
|
|
2179
|
-
logger = new import_common7.Logger(_DashboardSessionRequiredFilter.name);
|
|
2180
|
-
warned = false;
|
|
2181
|
-
constructor(auth = null) {
|
|
2182
|
-
this.auth = auth;
|
|
2183
|
-
}
|
|
2184
|
-
async catch(exception, host) {
|
|
2185
|
-
const http = host.switchToHttp();
|
|
2186
|
-
const response = http.getResponse();
|
|
2187
|
-
const hook = this.auth?.unauthenticatedPage;
|
|
2188
|
-
if (hook) {
|
|
2189
|
-
try {
|
|
2190
|
-
await hook({
|
|
2191
|
-
request: http.getRequest(),
|
|
2192
|
-
response,
|
|
2193
|
-
basePath: exception.basePath
|
|
2194
|
-
});
|
|
2195
|
-
if (responseAlreadyWritten(response)) return;
|
|
2196
|
-
this.warnOnce("dashboardAuth.unauthenticatedPage returned without writing a response; falling back to the built-in page. The hook must write AND end the response it is given.");
|
|
2197
|
-
} catch (error) {
|
|
2198
|
-
this.warnOnce(`dashboardAuth.unauthenticatedPage threw; falling back to the built-in page. ${String(error)}`);
|
|
2199
|
-
if (responseAlreadyWritten(response)) return;
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
writeHtmlRaw(response, renderSessionRequiredPage(exception.basePath), import_common7.HttpStatus.UNAUTHORIZED);
|
|
2203
|
-
}
|
|
2204
|
-
/** Once per process, not once per request: a broken hook fires on every denied navigation. */
|
|
2205
|
-
warnOnce(message) {
|
|
2206
|
-
if (this.warned) return;
|
|
2207
|
-
this.warned = true;
|
|
2208
|
-
this.logger.warn(message);
|
|
2209
|
-
}
|
|
2210
|
-
};
|
|
2211
|
-
DashboardSessionRequiredFilter = _ts_decorate7([
|
|
2212
|
-
(0, import_common7.Catch)(DashboardSessionRequiredException),
|
|
2213
|
-
_ts_param3(0, (0, import_common7.Optional)()),
|
|
2214
|
-
_ts_param3(0, (0, import_common7.Inject)(DASHBOARD_AUTH)),
|
|
2215
|
-
_ts_metadata5("design:type", Function),
|
|
2216
|
-
_ts_metadata5("design:paramtypes", [
|
|
2217
|
-
Object
|
|
2218
|
-
])
|
|
2219
|
-
], DashboardSessionRequiredFilter);
|
|
2220
|
-
|
|
2221
|
-
// src/server/durable-ui.controller.ts
|
|
2222
|
-
function _ts_decorate8(decorators, target, key, desc) {
|
|
2223
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2224
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2225
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2226
|
-
} else {
|
|
2227
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2228
|
-
if (d = decorators[i]) {
|
|
2229
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
}
|
|
2233
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2234
|
-
}
|
|
2235
|
-
__name(_ts_decorate8, "_ts_decorate");
|
|
2236
|
-
function _ts_metadata6(metadataKey, metadataValue) {
|
|
2237
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2238
|
-
return Reflect.metadata(metadataKey, metadataValue);
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
|
-
__name(_ts_metadata6, "_ts_metadata");
|
|
2242
|
-
function _ts_param4(paramIndex, decorator) {
|
|
2243
|
-
return function(target, key) {
|
|
2244
|
-
decorator(target, key, paramIndex);
|
|
2245
|
-
};
|
|
2246
|
-
}
|
|
2247
|
-
__name(_ts_param4, "_ts_param");
|
|
2248
1718
|
var DASHBOARD_BASE_PATH = Symbol("DASHBOARD_BASE_PATH");
|
|
2249
1719
|
var DASHBOARD_API_PATH = Symbol("DASHBOARD_API_PATH");
|
|
2250
1720
|
var BUILD_BASE = "/durable";
|
|
@@ -2261,9 +1731,9 @@ var CONTENT_TYPES = {
|
|
|
2261
1731
|
".woff2": "font/woff2",
|
|
2262
1732
|
".ico": "image/x-icon"
|
|
2263
1733
|
};
|
|
2264
|
-
var
|
|
1734
|
+
var DurableUiControllerBase = class {
|
|
2265
1735
|
static {
|
|
2266
|
-
__name(this, "
|
|
1736
|
+
__name(this, "DurableUiControllerBase");
|
|
2267
1737
|
}
|
|
2268
1738
|
basePath;
|
|
2269
1739
|
apiBasePath;
|
|
@@ -2277,7 +1747,7 @@ var DurableUiController = class {
|
|
|
2277
1747
|
index() {
|
|
2278
1748
|
const indexPath = (0, import_node_path.join)(this.dir, "index.html");
|
|
2279
1749
|
if (!(0, import_node_fs.existsSync)(indexPath)) {
|
|
2280
|
-
throw new
|
|
1750
|
+
throw new import_common6.NotFoundException("Dashboard is not built. Run the package build.");
|
|
2281
1751
|
}
|
|
2282
1752
|
const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
|
|
2283
1753
|
const inject = `<script>window.__DURABLE_BASE__='${this.basePath}';window.__DURABLE_API__='${this.apiBasePath}';</script>`;
|
|
@@ -2285,235 +1755,57 @@ var DurableUiController = class {
|
|
|
2285
1755
|
}
|
|
2286
1756
|
asset(file) {
|
|
2287
1757
|
const safe = (0, import_node_path.basename)(file);
|
|
2288
|
-
if (safe !== file) throw new
|
|
1758
|
+
if (safe !== file) throw new import_common6.NotFoundException();
|
|
2289
1759
|
const root = (0, import_node_path.resolve)(this.dir, "assets");
|
|
2290
1760
|
const assetPath = (0, import_node_path.resolve)(root, safe);
|
|
2291
1761
|
if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
|
|
2292
|
-
throw new
|
|
1762
|
+
throw new import_common6.NotFoundException();
|
|
2293
1763
|
}
|
|
2294
1764
|
const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
|
|
2295
|
-
return new
|
|
1765
|
+
return new import_common6.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
|
|
2296
1766
|
type
|
|
2297
1767
|
});
|
|
2298
1768
|
}
|
|
2299
1769
|
};
|
|
2300
|
-
|
|
2301
|
-
(0,
|
|
2302
|
-
(0,
|
|
2303
|
-
(0,
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
],
|
|
2308
|
-
|
|
2309
|
-
(0,
|
|
2310
|
-
(0,
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
1770
|
+
_ts_decorate6([
|
|
1771
|
+
(0, import_common6.Get)(),
|
|
1772
|
+
(0, import_common6.Header)("Content-Type", "text/html; charset=utf-8"),
|
|
1773
|
+
(0, import_common6.Header)("Cache-Control", "no-store, must-revalidate"),
|
|
1774
|
+
_ts_metadata5("design:type", Function),
|
|
1775
|
+
_ts_metadata5("design:paramtypes", []),
|
|
1776
|
+
_ts_metadata5("design:returntype", String)
|
|
1777
|
+
], DurableUiControllerBase.prototype, "index", null);
|
|
1778
|
+
_ts_decorate6([
|
|
1779
|
+
(0, import_common6.Get)("assets/:file"),
|
|
1780
|
+
(0, import_common6.Header)("Cache-Control", "public, max-age=31536000, immutable"),
|
|
1781
|
+
_ts_param3(0, (0, import_common6.Param)("file")),
|
|
1782
|
+
_ts_metadata5("design:type", Function),
|
|
1783
|
+
_ts_metadata5("design:paramtypes", [
|
|
2314
1784
|
String
|
|
2315
1785
|
]),
|
|
2316
|
-
|
|
2317
|
-
],
|
|
2318
|
-
|
|
2319
|
-
(0,
|
|
2320
|
-
(0,
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
_ts_metadata6("design:paramtypes", [
|
|
1786
|
+
_ts_metadata5("design:returntype", typeof import_common6.StreamableFile === "undefined" ? Object : import_common6.StreamableFile)
|
|
1787
|
+
], DurableUiControllerBase.prototype, "asset", null);
|
|
1788
|
+
DurableUiControllerBase = _ts_decorate6([
|
|
1789
|
+
(0, import_common6.Controller)(),
|
|
1790
|
+
_ts_param3(0, (0, import_common6.Inject)(DASHBOARD_BASE_PATH)),
|
|
1791
|
+
_ts_param3(1, (0, import_common6.Inject)(DASHBOARD_API_PATH)),
|
|
1792
|
+
_ts_metadata5("design:type", Function),
|
|
1793
|
+
_ts_metadata5("design:paramtypes", [
|
|
2325
1794
|
String,
|
|
2326
1795
|
String
|
|
2327
1796
|
])
|
|
2328
|
-
],
|
|
2329
|
-
|
|
2330
|
-
// src/server/durable-auth.controller.ts
|
|
2331
|
-
function _ts_decorate9(decorators, target, key, desc) {
|
|
2332
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2333
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2334
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2335
|
-
} else {
|
|
2336
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2337
|
-
if (d = decorators[i]) {
|
|
2338
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2339
|
-
}
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2343
|
-
}
|
|
2344
|
-
__name(_ts_decorate9, "_ts_decorate");
|
|
2345
|
-
function _ts_metadata7(metadataKey, metadataValue) {
|
|
2346
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2347
|
-
return Reflect.metadata(metadataKey, metadataValue);
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
__name(_ts_metadata7, "_ts_metadata");
|
|
2351
|
-
function _ts_param5(paramIndex, decorator) {
|
|
2352
|
-
return function(target, key) {
|
|
2353
|
-
decorator(target, key, paramIndex);
|
|
2354
|
-
};
|
|
2355
|
-
}
|
|
2356
|
-
__name(_ts_param5, "_ts_param");
|
|
2357
|
-
function isString(value) {
|
|
2358
|
-
return typeof value === "string";
|
|
2359
|
-
}
|
|
2360
|
-
__name(isString, "isString");
|
|
2361
|
-
var DurableAuthController = class _DurableAuthController {
|
|
1797
|
+
], DurableUiControllerBase);
|
|
1798
|
+
var DurableUiController = class extends DurableUiControllerBase {
|
|
2362
1799
|
static {
|
|
2363
|
-
__name(this, "
|
|
2364
|
-
}
|
|
2365
|
-
auth;
|
|
2366
|
-
basePath;
|
|
2367
|
-
logger = new import_common9.Logger(_DurableAuthController.name);
|
|
2368
|
-
/** Warn once per hook kind so a throwing hook doesn't spam logs on every failed attempt. */
|
|
2369
|
-
warnedHooks = /* @__PURE__ */ new Set();
|
|
2370
|
-
constructor(auth, basePath) {
|
|
2371
|
-
this.auth = auth;
|
|
2372
|
-
this.basePath = basePath;
|
|
2373
|
-
}
|
|
2374
|
-
// The login page reads `returnTo`/`error` from `location.search` client-side (see
|
|
2375
|
-
// `login-page.ts`), so this response never varies per request and needs no templating beyond
|
|
2376
|
-
// the developer-controlled `basePath`.
|
|
2377
|
-
loginPage() {
|
|
2378
|
-
const auth = this.requireAuth();
|
|
2379
|
-
if (!auth.modes.includes("login")) throw new import_common9.NotFoundException();
|
|
2380
|
-
return renderLoginPage(this.basePath);
|
|
2381
|
-
}
|
|
2382
|
-
// Called by the login page's own fetch (JSON, not a classic form POST — see `login-page.ts` for
|
|
2383
|
-
// why: it keeps the login page working with no host-configured body parser beyond the
|
|
2384
|
-
// JSON one Nest wires in by default on both Express and Fastify). Uniform `401` on any failure
|
|
2385
|
-
// (unknown user, wrong password, throwing hook) — no user-enumeration.
|
|
2386
|
-
async login(body, request, response) {
|
|
2387
|
-
const auth = this.requireAuth();
|
|
2388
|
-
if (!auth.modes.includes("login")) throw new import_common9.NotFoundException();
|
|
2389
|
-
if (!isString(body?.username) || !isString(body?.password)) {
|
|
2390
|
-
throw new import_common9.BadRequestException("Body must include string `username` and `password`.");
|
|
2391
|
-
}
|
|
2392
|
-
const { username, password } = body;
|
|
2393
|
-
const user = await this.runHook("login", () => auth.login?.(username, password) ?? null);
|
|
2394
|
-
if (!user) throw new import_common9.UnauthorizedException({
|
|
2395
|
-
message: "Invalid username or password."
|
|
2396
|
-
});
|
|
2397
|
-
issueSessionCookie(user, {
|
|
2398
|
-
auth,
|
|
2399
|
-
request,
|
|
2400
|
-
response
|
|
2401
|
-
});
|
|
2402
|
-
return {
|
|
2403
|
-
redirectTo: sanitizeReturnTo(body.returnTo, this.basePath)
|
|
2404
|
-
};
|
|
2405
|
-
}
|
|
2406
|
-
// Mode A: the host frontend (carrying its own auth) POSTs here; the host hook validates the raw
|
|
2407
|
-
// request and returns the session user, or `null` to deny. This is the SSO path — the host's own
|
|
2408
|
-
// guard decides, and no credential ever reaches this library.
|
|
2409
|
-
async session(request, response) {
|
|
2410
|
-
const auth = this.requireAuth();
|
|
2411
|
-
if (!auth.modes.includes("session")) throw new import_common9.NotFoundException();
|
|
2412
|
-
const user = await this.runHook("session", () => auth.session?.(request) ?? null);
|
|
2413
|
-
if (!user) throw new import_common9.UnauthorizedException();
|
|
2414
|
-
issueSessionCookie(user, {
|
|
2415
|
-
auth,
|
|
2416
|
-
request,
|
|
2417
|
-
response
|
|
2418
|
-
});
|
|
2419
|
-
}
|
|
2420
|
-
// Plain `GET` (not `POST`): logging out only ever destroys the CALLER's own session, so it's
|
|
2421
|
-
// safe/idempotent from the caller's perspective — a simple `<a href>` (no JS, no CSRF token)
|
|
2422
|
-
// works. Non-passthrough `@Res()`: this handler owns the response outright (clears the cookie,
|
|
2423
|
-
// then redirects), so Nest must not also try to send a return value afterwards.
|
|
2424
|
-
logout(request, response) {
|
|
2425
|
-
clearSessionCookie({
|
|
2426
|
-
request,
|
|
2427
|
-
response
|
|
2428
|
-
});
|
|
2429
|
-
redirectRaw(response, this.auth?.modes.includes("login") ? `${this.basePath}/login` : this.basePath);
|
|
2430
|
-
}
|
|
2431
|
-
requireAuth() {
|
|
2432
|
-
if (!this.auth) throw new import_common9.NotFoundException();
|
|
2433
|
-
return this.auth;
|
|
2434
|
-
}
|
|
2435
|
-
/**
|
|
2436
|
-
* Run a host hook (`login` or `session`) defensively: a throw is treated as a denial (uniform
|
|
2437
|
-
* failure) and warn-logged once PER KIND, so a buggy hook never 500s the endpoint into a
|
|
2438
|
-
* stack-trace leak nor floods the logs on repeated bad attempts.
|
|
2439
|
-
*/
|
|
2440
|
-
async runHook(kind, run) {
|
|
2441
|
-
try {
|
|
2442
|
-
return await run() ?? null;
|
|
2443
|
-
} catch (error) {
|
|
2444
|
-
if (!this.warnedHooks.has(kind)) {
|
|
2445
|
-
this.warnedHooks.add(kind);
|
|
2446
|
-
this.logger.warn(`dashboardAuth ${kind} hook threw; treating as denial. ${error instanceof Error ? error.message : String(error)}`);
|
|
2447
|
-
}
|
|
2448
|
-
return null;
|
|
2449
|
-
}
|
|
1800
|
+
__name(this, "DurableUiController");
|
|
2450
1801
|
}
|
|
2451
1802
|
};
|
|
2452
|
-
|
|
2453
|
-
(0,
|
|
2454
|
-
|
|
2455
|
-
(0, import_common9.Header)("Cache-Control", "no-store, must-revalidate"),
|
|
2456
|
-
_ts_metadata7("design:type", Function),
|
|
2457
|
-
_ts_metadata7("design:paramtypes", []),
|
|
2458
|
-
_ts_metadata7("design:returntype", String)
|
|
2459
|
-
], DurableAuthController.prototype, "loginPage", null);
|
|
2460
|
-
_ts_decorate9([
|
|
2461
|
-
(0, import_common9.Post)("login"),
|
|
2462
|
-
(0, import_common9.HttpCode)(200),
|
|
2463
|
-
_ts_param5(0, (0, import_common9.Body)()),
|
|
2464
|
-
_ts_param5(1, (0, import_common9.Req)()),
|
|
2465
|
-
_ts_param5(2, (0, import_common9.Res)({
|
|
2466
|
-
passthrough: true
|
|
2467
|
-
})),
|
|
2468
|
-
_ts_metadata7("design:type", Function),
|
|
2469
|
-
_ts_metadata7("design:paramtypes", [
|
|
2470
|
-
typeof LoginBody === "undefined" ? Object : LoginBody,
|
|
2471
|
-
Object,
|
|
2472
|
-
Object
|
|
2473
|
-
]),
|
|
2474
|
-
_ts_metadata7("design:returntype", Promise)
|
|
2475
|
-
], DurableAuthController.prototype, "login", null);
|
|
2476
|
-
_ts_decorate9([
|
|
2477
|
-
(0, import_common9.Post)("session"),
|
|
2478
|
-
(0, import_common9.HttpCode)(204),
|
|
2479
|
-
_ts_param5(0, (0, import_common9.Req)()),
|
|
2480
|
-
_ts_param5(1, (0, import_common9.Res)({
|
|
2481
|
-
passthrough: true
|
|
2482
|
-
})),
|
|
2483
|
-
_ts_metadata7("design:type", Function),
|
|
2484
|
-
_ts_metadata7("design:paramtypes", [
|
|
2485
|
-
Object,
|
|
2486
|
-
Object
|
|
2487
|
-
]),
|
|
2488
|
-
_ts_metadata7("design:returntype", Promise)
|
|
2489
|
-
], DurableAuthController.prototype, "session", null);
|
|
2490
|
-
_ts_decorate9([
|
|
2491
|
-
(0, import_common9.Get)("logout"),
|
|
2492
|
-
_ts_param5(0, (0, import_common9.Req)()),
|
|
2493
|
-
_ts_param5(1, (0, import_common9.Res)()),
|
|
2494
|
-
_ts_metadata7("design:type", Function),
|
|
2495
|
-
_ts_metadata7("design:paramtypes", [
|
|
2496
|
-
Object,
|
|
2497
|
-
Object
|
|
2498
|
-
]),
|
|
2499
|
-
_ts_metadata7("design:returntype", void 0)
|
|
2500
|
-
], DurableAuthController.prototype, "logout", null);
|
|
2501
|
-
DurableAuthController = _ts_decorate9([
|
|
2502
|
-
(0, import_common9.Controller)(),
|
|
2503
|
-
_ts_param5(0, (0, import_common9.Optional)()),
|
|
2504
|
-
_ts_param5(0, (0, import_common9.Inject)(DASHBOARD_AUTH)),
|
|
2505
|
-
_ts_param5(1, (0, import_common9.Inject)(DASHBOARD_BASE_PATH)),
|
|
2506
|
-
_ts_metadata7("design:type", Function),
|
|
2507
|
-
_ts_metadata7("design:paramtypes", [
|
|
2508
|
-
Object,
|
|
2509
|
-
String
|
|
2510
|
-
])
|
|
2511
|
-
], DurableAuthController);
|
|
1803
|
+
DurableUiController = _ts_decorate6([
|
|
1804
|
+
(0, import_common6.Controller)()
|
|
1805
|
+
], DurableUiController);
|
|
2512
1806
|
|
|
2513
|
-
// src/server/durable-dashboard
|
|
2514
|
-
|
|
2515
|
-
var import_common10 = require("@nestjs/common");
|
|
2516
|
-
function _ts_decorate10(decorators, target, key, desc) {
|
|
1807
|
+
// src/server/durable-dashboard.module.ts
|
|
1808
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
2517
1809
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2518
1810
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2519
1811
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2526,342 +1818,59 @@ function _ts_decorate10(decorators, target, key, desc) {
|
|
|
2526
1818
|
}
|
|
2527
1819
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2528
1820
|
}
|
|
2529
|
-
__name(
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
decorator(target, key, paramIndex);
|
|
2539
|
-
};
|
|
2540
|
-
}
|
|
2541
|
-
__name(_ts_param6, "_ts_param");
|
|
2542
|
-
var DURABLE_DASHBOARD_TOKEN_ENV = "DURABLE_DASHBOARD_TOKEN";
|
|
2543
|
-
var DASHBOARD_GATE = Symbol("DASHBOARD_GATE");
|
|
2544
|
-
var LOG_CONTEXT = "DurableDashboard";
|
|
2545
|
-
var HOW_TO_CONFIGURE = [
|
|
2546
|
-
"Configure one of: `guards: [YourAuthGuard]`, `dashboardAuth: { secret, session | login }`",
|
|
2547
|
-
"(or `useDashboardAuth` in forRootAsync), a bearer token via the `token` option or the",
|
|
2548
|
-
`${DURABLE_DASHBOARD_TOKEN_ENV} env var, or \`allowUnauthenticated: true\` when the console is`,
|
|
2549
|
-
"already protected outside this module (a global guard, a reverse proxy, a private network)."
|
|
1821
|
+
__name(_ts_decorate7, "_ts_decorate");
|
|
1822
|
+
markOpenToAuthorization(DurableApiController);
|
|
1823
|
+
markOpenToAuthorization(DurableUiController);
|
|
1824
|
+
var DASHBOARD_PROTECTION_CHECK = Symbol("DASHBOARD_PROTECTION_CHECK");
|
|
1825
|
+
var UNPROTECTED_CONSOLE_IN_PRODUCTION = [
|
|
1826
|
+
"DurableDashboardModule: NODE_ENV=production and the durable console is mounted with no",
|
|
1827
|
+
"protection, so the app refuses to boot. Protect it one of two ways:",
|
|
1828
|
+
"(1) decorators on the mounted console: DurableDashboardModule.forRoot({ decorators: [UseGuards(AuthenticationGuard), Can(ConsolePolicy, 'view')] });",
|
|
1829
|
+
"(2) mount it yourself: DurableDashboardModule.forRoot({ routes: false }) plus @Controller('durable') @UseGuards(AuthenticationGuard) @Can(ConsolePolicy, 'view') class ConsoleUi extends DurableUiControllerBase {} (and the same over DurableApiControllerBase at 'durable/api')."
|
|
2550
1830
|
].join(" ");
|
|
2551
1831
|
function isProduction() {
|
|
2552
1832
|
return (process.env.NODE_ENV ?? "").trim().toLowerCase() === "production";
|
|
2553
1833
|
}
|
|
2554
1834
|
__name(isProduction, "isProduction");
|
|
2555
|
-
function
|
|
2556
|
-
if (options.hasGuards || auth !== null) return {
|
|
2557
|
-
mode: "delegated"
|
|
2558
|
-
};
|
|
2559
|
-
const token = options.token ?? process.env[DURABLE_DASHBOARD_TOKEN_ENV];
|
|
2560
|
-
if (typeof token === "string" && token !== "") return {
|
|
2561
|
-
mode: "token",
|
|
2562
|
-
token
|
|
2563
|
-
};
|
|
2564
|
-
if (options.allowUnauthenticated === true) return {
|
|
2565
|
-
mode: "open"
|
|
2566
|
-
};
|
|
1835
|
+
function protectionCheckProvider() {
|
|
2567
1836
|
return {
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
switch (gate.mode) {
|
|
2574
|
-
case "open":
|
|
2575
|
-
logger.warn("allowUnauthenticated: true. The durable console (including retry/cancel and other mutating endpoints) is served with NO authentication from this module. Only do this when a global guard or reverse proxy already protects it.");
|
|
2576
|
-
return;
|
|
2577
|
-
case "token":
|
|
2578
|
-
if (options.allowUnauthenticated === true) {
|
|
2579
|
-
logger.warn("allowUnauthenticated: true is ignored because a dashboard token is configured; requests must carry the token.");
|
|
2580
|
-
}
|
|
2581
|
-
return;
|
|
2582
|
-
case "unconfigured":
|
|
2583
|
-
logger.warn([
|
|
2584
|
-
"The durable console is UNAUTHENTICATED: no guards, dashboardAuth, token or",
|
|
2585
|
-
"allowUnauthenticated were configured. It is served open because NODE_ENV is not",
|
|
2586
|
-
'"production", but it WILL deny every request when NODE_ENV=production.',
|
|
2587
|
-
HOW_TO_CONFIGURE
|
|
2588
|
-
].join(" "));
|
|
2589
|
-
return;
|
|
2590
|
-
case "deny":
|
|
2591
|
-
logger.error([
|
|
2592
|
-
"The durable console has no authentication configured and NODE_ENV=production, so it",
|
|
2593
|
-
"is failing closed: every console request (UI and API) is denied.",
|
|
2594
|
-
HOW_TO_CONFIGURE
|
|
2595
|
-
].join(" "));
|
|
2596
|
-
return;
|
|
2597
|
-
case "delegated":
|
|
2598
|
-
return;
|
|
2599
|
-
}
|
|
2600
|
-
}
|
|
2601
|
-
__name(reportDashboardGate, "reportDashboardGate");
|
|
2602
|
-
function dashboardGateProvider(options) {
|
|
2603
|
-
return {
|
|
2604
|
-
provide: DASHBOARD_GATE,
|
|
2605
|
-
inject: [
|
|
2606
|
-
DASHBOARD_AUTH
|
|
2607
|
-
],
|
|
2608
|
-
useFactory: /* @__PURE__ */ __name((auth) => {
|
|
2609
|
-
const gate = resolveDashboardGate(options, auth);
|
|
2610
|
-
reportDashboardGate(gate, options);
|
|
2611
|
-
return gate;
|
|
1837
|
+
provide: DASHBOARD_PROTECTION_CHECK,
|
|
1838
|
+
useFactory: /* @__PURE__ */ __name(() => {
|
|
1839
|
+
if (isProduction()) throw new Error(UNPROTECTED_CONSOLE_IN_PRODUCTION);
|
|
1840
|
+
new import_common7.Logger("DurableDashboard").warn("The durable console is mounted with no `decorators`, so it is served OPEN (retry/cancel included). That is refused when NODE_ENV=production: pass `decorators` (e.g. [UseGuards(AuthenticationGuard), Can(ConsolePolicy, 'view')]) or mount it yourself with `routes: false`.");
|
|
1841
|
+
return true;
|
|
2612
1842
|
}, "useFactory")
|
|
2613
1843
|
};
|
|
2614
1844
|
}
|
|
2615
|
-
__name(
|
|
2616
|
-
function
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
return void 0;
|
|
2627
|
-
}
|
|
2628
|
-
__name(headerValue, "headerValue");
|
|
2629
|
-
function readDashboardToken(request) {
|
|
2630
|
-
if (!isRecord3(request)) return void 0;
|
|
2631
|
-
const authorization = headerValue(request, "authorization");
|
|
2632
|
-
if (authorization) {
|
|
2633
|
-
const match = /^Bearer\s+(.+)$/i.exec(authorization);
|
|
2634
|
-
if (match?.[1]) return match[1].trim();
|
|
2635
|
-
}
|
|
2636
|
-
const header = headerValue(request, "x-durable-token");
|
|
2637
|
-
if (header) return header.trim();
|
|
2638
|
-
const method = typeof request.method === "string" ? request.method.toUpperCase() : "";
|
|
2639
|
-
if (method === "GET" || method === "HEAD") {
|
|
2640
|
-
const query = request.query;
|
|
2641
|
-
if (isRecord3(query)) {
|
|
2642
|
-
const value = query.token;
|
|
2643
|
-
if (typeof value === "string" && value !== "") return value;
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
return void 0;
|
|
2647
|
-
}
|
|
2648
|
-
__name(readDashboardToken, "readDashboardToken");
|
|
2649
|
-
function secretsMatch(provided, expected) {
|
|
2650
|
-
const a = Buffer.from(provided);
|
|
2651
|
-
const b = Buffer.from(expected);
|
|
2652
|
-
if (a.length !== b.length) return false;
|
|
2653
|
-
return (0, import_node_crypto2.timingSafeEqual)(a, b);
|
|
2654
|
-
}
|
|
2655
|
-
__name(secretsMatch, "secretsMatch");
|
|
2656
|
-
var DurableDashboardGateGuard = class {
|
|
2657
|
-
static {
|
|
2658
|
-
__name(this, "DurableDashboardGateGuard");
|
|
2659
|
-
}
|
|
2660
|
-
gate;
|
|
2661
|
-
constructor(gate) {
|
|
2662
|
-
this.gate = gate;
|
|
2663
|
-
}
|
|
2664
|
-
canActivate(context) {
|
|
2665
|
-
switch (this.gate.mode) {
|
|
2666
|
-
case "delegated":
|
|
2667
|
-
case "open":
|
|
2668
|
-
case "unconfigured":
|
|
2669
|
-
return true;
|
|
2670
|
-
case "deny":
|
|
2671
|
-
throw new import_common10.ForbiddenException([
|
|
2672
|
-
"Durable dashboard authentication is not configured, and NODE_ENV=production denies",
|
|
2673
|
-
"an unauthenticated console.",
|
|
2674
|
-
HOW_TO_CONFIGURE
|
|
2675
|
-
].join(" "));
|
|
2676
|
-
case "token": {
|
|
2677
|
-
const provided = readDashboardToken(context.switchToHttp().getRequest());
|
|
2678
|
-
if (provided !== void 0 && secretsMatch(provided, this.gate.token ?? "")) return true;
|
|
2679
|
-
throw new import_common10.UnauthorizedException("A valid durable dashboard token is required (Authorization: Bearer <token>, x-durable-token, or ?token= on GET).");
|
|
2680
|
-
}
|
|
2681
|
-
}
|
|
2682
|
-
}
|
|
2683
|
-
};
|
|
2684
|
-
DurableDashboardGateGuard = _ts_decorate10([
|
|
2685
|
-
(0, import_common10.Injectable)(),
|
|
2686
|
-
_ts_param6(0, (0, import_common10.Inject)(DASHBOARD_GATE)),
|
|
2687
|
-
_ts_metadata8("design:type", Function),
|
|
2688
|
-
_ts_metadata8("design:paramtypes", [
|
|
2689
|
-
typeof DashboardGate === "undefined" ? Object : DashboardGate
|
|
2690
|
-
])
|
|
2691
|
-
], DurableDashboardGateGuard);
|
|
2692
|
-
|
|
2693
|
-
// src/server/durable-dashboard.module.ts
|
|
2694
|
-
var import_reflect_metadata = require("reflect-metadata");
|
|
2695
|
-
var import_nestjs_filter3 = require("@dudousxd/nestjs-filter");
|
|
2696
|
-
var import_common12 = require("@nestjs/common");
|
|
2697
|
-
var import_core = require("@nestjs/core");
|
|
2698
|
-
|
|
2699
|
-
// src/server/durable-session.guard.ts
|
|
2700
|
-
var import_common11 = require("@nestjs/common");
|
|
2701
|
-
function _ts_decorate11(decorators, target, key, desc) {
|
|
2702
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2703
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2704
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2705
|
-
} else {
|
|
2706
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2707
|
-
if (d = decorators[i]) {
|
|
2708
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2709
|
-
}
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2713
|
-
}
|
|
2714
|
-
__name(_ts_decorate11, "_ts_decorate");
|
|
2715
|
-
function _ts_metadata9(metadataKey, metadataValue) {
|
|
2716
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
2717
|
-
return Reflect.metadata(metadataKey, metadataValue);
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
__name(_ts_metadata9, "_ts_metadata");
|
|
2721
|
-
function _ts_param7(paramIndex, decorator) {
|
|
2722
|
-
return function(target, key) {
|
|
2723
|
-
decorator(target, key, paramIndex);
|
|
2724
|
-
};
|
|
2725
|
-
}
|
|
2726
|
-
__name(_ts_param7, "_ts_param");
|
|
2727
|
-
var DurableUiSessionGuard = class {
|
|
2728
|
-
static {
|
|
2729
|
-
__name(this, "DurableUiSessionGuard");
|
|
2730
|
-
}
|
|
2731
|
-
auth;
|
|
2732
|
-
basePath;
|
|
2733
|
-
constructor(auth, basePath) {
|
|
2734
|
-
this.auth = auth;
|
|
2735
|
-
this.basePath = basePath;
|
|
2736
|
-
}
|
|
2737
|
-
async canActivate(context) {
|
|
2738
|
-
if (!this.auth) return true;
|
|
2739
|
-
const auth = this.auth;
|
|
2740
|
-
const http = context.switchToHttp();
|
|
2741
|
-
const request = http.getRequest();
|
|
2742
|
-
const session = readSessionFromRequest(auth, request);
|
|
2743
|
-
if (!session) {
|
|
2744
|
-
this.denyUnauthenticated(auth, request);
|
|
2745
|
-
}
|
|
2746
|
-
if (!await maybeRenewSession(auth, session, request, http.getResponse())) {
|
|
2747
|
-
this.denyUnauthenticated(auth, request);
|
|
2748
|
-
}
|
|
2749
|
-
return true;
|
|
2750
|
-
}
|
|
2751
|
-
/**
|
|
2752
|
-
* A revoked session (the host's `revalidate` hook says no) is denied exactly like an absent
|
|
2753
|
-
* one — by design, there is nothing left to distinguish "never had a session" from "had one,
|
|
2754
|
-
* then lost it" once the cookie is cleared, so both get the same Mode-aware treatment.
|
|
2755
|
-
*
|
|
2756
|
-
* Takes `auth` explicitly rather than reading `this.auth`: `canActivate`'s `!this.auth` early
|
|
2757
|
-
* return narrows the field within that method only — TS doesn't carry it across a method call
|
|
2758
|
-
* — so callers pass the already-narrowed value instead of this method re-deriving (or
|
|
2759
|
-
* asserting away) the nullability.
|
|
2760
|
-
*/
|
|
2761
|
-
denyUnauthenticated(auth, request) {
|
|
2762
|
-
if (!auth.modes.includes("login")) throw new DashboardSessionRequiredException(this.basePath);
|
|
2763
|
-
const returnTo = encodeURIComponent(originalRequestUrl(request));
|
|
2764
|
-
throw new DashboardLoginRedirectException(`${this.basePath}/login?returnTo=${returnTo}`);
|
|
2765
|
-
}
|
|
2766
|
-
};
|
|
2767
|
-
DurableUiSessionGuard = _ts_decorate11([
|
|
2768
|
-
(0, import_common11.Injectable)(),
|
|
2769
|
-
_ts_param7(0, (0, import_common11.Inject)(DASHBOARD_AUTH)),
|
|
2770
|
-
_ts_param7(1, (0, import_common11.Inject)(DASHBOARD_BASE_PATH)),
|
|
2771
|
-
_ts_metadata9("design:type", Function),
|
|
2772
|
-
_ts_metadata9("design:paramtypes", [
|
|
2773
|
-
Object,
|
|
2774
|
-
String
|
|
2775
|
-
])
|
|
2776
|
-
], DurableUiSessionGuard);
|
|
2777
|
-
var DurableApiSessionGuard = class {
|
|
2778
|
-
static {
|
|
2779
|
-
__name(this, "DurableApiSessionGuard");
|
|
2780
|
-
}
|
|
2781
|
-
auth;
|
|
2782
|
-
constructor(auth) {
|
|
2783
|
-
this.auth = auth;
|
|
2784
|
-
}
|
|
2785
|
-
async canActivate(context) {
|
|
2786
|
-
if (!this.auth) return true;
|
|
2787
|
-
const auth = this.auth;
|
|
2788
|
-
const http = context.switchToHttp();
|
|
2789
|
-
const request = http.getRequest();
|
|
2790
|
-
const session = readSessionFromRequest(auth, request);
|
|
2791
|
-
if (!session) throw this.unauthorized(auth);
|
|
2792
|
-
if (!await maybeRenewSession(auth, session, request, http.getResponse())) {
|
|
2793
|
-
throw this.unauthorized(auth);
|
|
2794
|
-
}
|
|
2795
|
-
return true;
|
|
2796
|
-
}
|
|
2797
|
-
/**
|
|
2798
|
-
* A bare 401 body carrying `{ auth: { modes } }` — mirrors `@dudousxd/nestjs-telescope`'s
|
|
2799
|
-
* dashboardAuth 401. The API is fetched (never navigated), so this is the ONLY way the console
|
|
2800
|
-
* SPA (`durable-client.ts`) learns which auth surface to send the operator to on a mid-session
|
|
2801
|
-
* 401; `DurableUiSessionGuard`'s redirect/session-required exceptions above don't reach it.
|
|
2802
|
-
*/
|
|
2803
|
-
unauthorized(auth) {
|
|
2804
|
-
return new import_common11.UnauthorizedException({
|
|
2805
|
-
auth: {
|
|
2806
|
-
modes: auth.modes
|
|
2807
|
-
}
|
|
2808
|
-
});
|
|
2809
|
-
}
|
|
2810
|
-
};
|
|
2811
|
-
DurableApiSessionGuard = _ts_decorate11([
|
|
2812
|
-
(0, import_common11.Injectable)(),
|
|
2813
|
-
_ts_param7(0, (0, import_common11.Inject)(DASHBOARD_AUTH)),
|
|
2814
|
-
_ts_metadata9("design:type", Function),
|
|
2815
|
-
_ts_metadata9("design:paramtypes", [
|
|
2816
|
-
Object
|
|
2817
|
-
])
|
|
2818
|
-
], DurableApiSessionGuard);
|
|
2819
|
-
|
|
2820
|
-
// src/server/durable-dashboard.module.ts
|
|
2821
|
-
function _ts_decorate12(decorators, target, key, desc) {
|
|
2822
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2823
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
2824
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2825
|
-
} else {
|
|
2826
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2827
|
-
if (d = decorators[i]) {
|
|
2828
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2829
|
-
}
|
|
2830
|
-
}
|
|
2831
|
-
}
|
|
2832
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2833
|
-
}
|
|
2834
|
-
__name(_ts_decorate12, "_ts_decorate");
|
|
2835
|
-
var GUARDS_METADATA = "__guards__";
|
|
1845
|
+
__name(protectionCheckProvider, "protectionCheckProvider");
|
|
1846
|
+
function assertNothingToDecorate(options) {
|
|
1847
|
+
if (options.decorators === void 0) return;
|
|
1848
|
+
throw new Error([
|
|
1849
|
+
"DurableDashboardModule.forRoot({ routes: false }) mounts no controllers, so `decorators`",
|
|
1850
|
+
"would protect nothing. Put your protection on the controllers you mount (extend",
|
|
1851
|
+
"DurableUiControllerBase / DurableApiControllerBase and decorate them with @UseGuards /",
|
|
1852
|
+
"@Can), and drop `decorators`."
|
|
1853
|
+
].join(" "));
|
|
1854
|
+
}
|
|
1855
|
+
__name(assertNothingToDecorate, "assertNothingToDecorate");
|
|
2836
1856
|
function normalize(path) {
|
|
2837
1857
|
return `/${path.replace(/^\/+|\/+$/g, "")}`;
|
|
2838
1858
|
}
|
|
2839
1859
|
__name(normalize, "normalize");
|
|
2840
|
-
function stampGuards(hostGuards, builtIn, controller) {
|
|
2841
|
-
const merged = [
|
|
2842
|
-
...builtIn.filter((guard) => guard !== void 0),
|
|
2843
|
-
...hostGuards ?? []
|
|
2844
|
-
];
|
|
2845
|
-
Reflect.defineMetadata(GUARDS_METADATA, merged, controller);
|
|
2846
|
-
}
|
|
2847
|
-
__name(stampGuards, "stampGuards");
|
|
2848
1860
|
var DurableApiModule = class _DurableApiModule {
|
|
2849
1861
|
static {
|
|
2850
1862
|
__name(this, "DurableApiModule");
|
|
2851
1863
|
}
|
|
2852
1864
|
static register(options) {
|
|
2853
|
-
|
|
2854
|
-
options.authMayBeConfigured ? DurableApiSessionGuard : void 0,
|
|
2855
|
-
options.stampGate ? DurableDashboardGateGuard : void 0
|
|
2856
|
-
], DurableApiController);
|
|
1865
|
+
const routes = options.routes !== false;
|
|
2857
1866
|
return {
|
|
2858
1867
|
module: _DurableApiModule,
|
|
2859
1868
|
imports: [
|
|
2860
1869
|
...options.imports ?? []
|
|
2861
1870
|
],
|
|
2862
|
-
controllers: [
|
|
2863
|
-
DurableApiController
|
|
2864
|
-
],
|
|
1871
|
+
controllers: routes ? [
|
|
1872
|
+
controllerFor(DurableApiController, options.decorators)
|
|
1873
|
+
] : [],
|
|
2865
1874
|
providers: [
|
|
2866
1875
|
DashboardService,
|
|
2867
1876
|
// `@dudousxd/nestjs-filter` is wired PRIVATELY here rather than through
|
|
@@ -2894,82 +1903,81 @@ var DurableApiModule = class _DurableApiModule {
|
|
|
2894
1903
|
provide: RUN_QUERY_ADAPTER,
|
|
2895
1904
|
useExisting: RunQueryAdapter
|
|
2896
1905
|
},
|
|
2897
|
-
RunFilter
|
|
2898
|
-
options.authProvider,
|
|
2899
|
-
DurableApiSessionGuard,
|
|
2900
|
-
// Resolved ONCE here (this module is imported by the UI module, which reuses it via the
|
|
2901
|
-
// export below), so the boot report is logged once per mount.
|
|
2902
|
-
dashboardGateProvider(options.gate),
|
|
2903
|
-
DurableDashboardGateGuard,
|
|
2904
|
-
...options.guards ?? []
|
|
1906
|
+
RunFilter
|
|
2905
1907
|
],
|
|
2906
|
-
|
|
1908
|
+
// Self-mounted (`routes: false`): the host's own subclass of `DurableApiControllerBase` is
|
|
1909
|
+
// hosted in the HOST's module, so what its constructor injects must be exported. `FilterRunner`
|
|
1910
|
+
// is only exported then: exporting it from a mounted console would shadow a host's own
|
|
1911
|
+
// `FilterModule` runner in whatever module imports the dashboard.
|
|
1912
|
+
exports: routes ? [
|
|
1913
|
+
DashboardService
|
|
1914
|
+
] : [
|
|
2907
1915
|
DashboardService,
|
|
2908
|
-
|
|
1916
|
+
import_nestjs_filter3.FilterRunner
|
|
2909
1917
|
]
|
|
2910
1918
|
};
|
|
2911
1919
|
}
|
|
2912
1920
|
};
|
|
2913
|
-
DurableApiModule =
|
|
2914
|
-
(0,
|
|
1921
|
+
DurableApiModule = _ts_decorate7([
|
|
1922
|
+
(0, import_common7.Module)({})
|
|
2915
1923
|
], DurableApiModule);
|
|
2916
1924
|
var DurableDashboardModule = class _DurableDashboardModule {
|
|
2917
1925
|
static {
|
|
2918
1926
|
__name(this, "DurableDashboardModule");
|
|
2919
1927
|
}
|
|
2920
1928
|
static forRoot(options = {}) {
|
|
2921
|
-
const authProvider = {
|
|
2922
|
-
provide: DASHBOARD_AUTH,
|
|
2923
|
-
useValue: resolveDashboardAuth(options.dashboardAuth)
|
|
2924
|
-
};
|
|
2925
|
-
const authConfigured = options.dashboardAuth !== void 0;
|
|
2926
|
-
return _DurableDashboardModule.build(options, authProvider, authConfigured, authConfigured);
|
|
2927
|
-
}
|
|
2928
|
-
static forRootAsync(options) {
|
|
2929
|
-
const authProvider = {
|
|
2930
|
-
provide: DASHBOARD_AUTH,
|
|
2931
|
-
inject: options.inject ?? [],
|
|
2932
|
-
useFactory: /* @__PURE__ */ __name(async (...deps) => resolveDashboardAuth(await options.useDashboardAuth(...deps)), "useFactory")
|
|
2933
|
-
};
|
|
2934
|
-
return _DurableDashboardModule.build(options, authProvider, true, false);
|
|
2935
|
-
}
|
|
2936
|
-
/** Shared wiring: static routing + the API module, with `dashboardAuth` supplied by `authProvider`. */
|
|
2937
|
-
static build(options, authProvider, authMayBeConfigured, authStaticallyConfigured) {
|
|
2938
1929
|
const basePath = normalize(options.basePath ?? "/durable");
|
|
2939
1930
|
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
2940
|
-
const
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
}
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
1931
|
+
const pathProviders = [
|
|
1932
|
+
{
|
|
1933
|
+
provide: DASHBOARD_BASE_PATH,
|
|
1934
|
+
useValue: basePath
|
|
1935
|
+
},
|
|
1936
|
+
{
|
|
1937
|
+
provide: DASHBOARD_API_PATH,
|
|
1938
|
+
useValue: apiBasePath
|
|
1939
|
+
}
|
|
1940
|
+
];
|
|
1941
|
+
if (options.routes === false) {
|
|
1942
|
+
assertNothingToDecorate(options);
|
|
1943
|
+
const api = DurableApiModule.register({
|
|
1944
|
+
...options.imports ? {
|
|
1945
|
+
imports: options.imports
|
|
1946
|
+
} : {},
|
|
1947
|
+
routes: false
|
|
1948
|
+
});
|
|
1949
|
+
return {
|
|
1950
|
+
module: _DurableDashboardModule,
|
|
1951
|
+
imports: [
|
|
1952
|
+
...options.imports ?? [],
|
|
1953
|
+
api
|
|
1954
|
+
],
|
|
1955
|
+
controllers: [],
|
|
1956
|
+
providers: pathProviders,
|
|
1957
|
+
// What a host's subclasses of `DurableUiControllerBase` / `DurableApiControllerBase` inject:
|
|
1958
|
+
// the SPA's paths, and the read/action service and the filter runner via the API module.
|
|
1959
|
+
exports: [
|
|
1960
|
+
DurableApiModule,
|
|
1961
|
+
DASHBOARD_BASE_PATH,
|
|
1962
|
+
DASHBOARD_API_PATH
|
|
1963
|
+
]
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
const decorated = (options.decorators?.length ?? 0) > 0;
|
|
2955
1967
|
return {
|
|
2956
1968
|
module: _DurableDashboardModule,
|
|
2957
1969
|
imports: [
|
|
2958
1970
|
...options.imports ?? [],
|
|
2959
|
-
//
|
|
2960
|
-
//
|
|
1971
|
+
// Host imports must reach the API controller's HOST module: enhancers resolve from their
|
|
1972
|
+
// controller's own module, never from a parent (see DurableApiModule.register).
|
|
2961
1973
|
// Spread-only-when-set: exactOptionalPropertyTypes rejects an explicit `undefined`.
|
|
2962
1974
|
DurableApiModule.register({
|
|
2963
1975
|
...options.imports ? {
|
|
2964
1976
|
imports: options.imports
|
|
2965
1977
|
} : {},
|
|
2966
|
-
...options.
|
|
2967
|
-
|
|
2968
|
-
} : {}
|
|
2969
|
-
authProvider,
|
|
2970
|
-
authMayBeConfigured,
|
|
2971
|
-
gate,
|
|
2972
|
-
stampGate
|
|
1978
|
+
...options.decorators ? {
|
|
1979
|
+
decorators: options.decorators
|
|
1980
|
+
} : {}
|
|
2973
1981
|
}),
|
|
2974
1982
|
import_core.RouterModule.register([
|
|
2975
1983
|
{
|
|
@@ -2983,30 +1991,13 @@ var DurableDashboardModule = class _DurableDashboardModule {
|
|
|
2983
1991
|
])
|
|
2984
1992
|
],
|
|
2985
1993
|
controllers: [
|
|
2986
|
-
DurableUiController,
|
|
2987
|
-
// The auth controller (login page + logout) only exists when dashboardAuth might be
|
|
2988
|
-
// configured — mounting it unconditionally would add a new `/login` route even for hosts
|
|
2989
|
-
// that never set `dashboardAuth`, breaking "absent -> today's behavior byte-for-byte".
|
|
2990
|
-
...authMayBeConfigured ? [
|
|
2991
|
-
DurableAuthController
|
|
2992
|
-
] : []
|
|
1994
|
+
controllerFor(DurableUiController, options.decorators)
|
|
2993
1995
|
],
|
|
2994
1996
|
providers: [
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
{
|
|
3000
|
-
provide: DASHBOARD_API_PATH,
|
|
3001
|
-
useValue: apiBasePath
|
|
3002
|
-
},
|
|
3003
|
-
authProvider,
|
|
3004
|
-
DurableUiSessionGuard,
|
|
3005
|
-
// `DASHBOARD_GATE` itself comes from the imported DurableApiModule (resolved once there).
|
|
3006
|
-
DurableDashboardGateGuard,
|
|
3007
|
-
// DurableUiController (and DurableAuthController, when present) are hosted HERE, so their
|
|
3008
|
-
// guards DI-instantiate from this module.
|
|
3009
|
-
...options.guards ?? []
|
|
1997
|
+
...pathProviders,
|
|
1998
|
+
...decorated ? [] : [
|
|
1999
|
+
protectionCheckProvider()
|
|
2000
|
+
]
|
|
3010
2001
|
],
|
|
3011
2002
|
// Re-export the API module so its DashboardService reaches importers (e.g. flip's own controllers).
|
|
3012
2003
|
exports: [
|
|
@@ -3015,27 +2006,21 @@ var DurableDashboardModule = class _DurableDashboardModule {
|
|
|
3015
2006
|
};
|
|
3016
2007
|
}
|
|
3017
2008
|
};
|
|
3018
|
-
DurableDashboardModule =
|
|
3019
|
-
(0,
|
|
2009
|
+
DurableDashboardModule = _ts_decorate7([
|
|
2010
|
+
(0, import_common7.Module)({})
|
|
3020
2011
|
], DurableDashboardModule);
|
|
3021
2012
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3022
2013
|
0 && (module.exports = {
|
|
3023
2014
|
DASHBOARD_API_PATH,
|
|
3024
2015
|
DASHBOARD_BASE_PATH,
|
|
3025
|
-
|
|
3026
|
-
DURABLE_DASHBOARD_TOKEN_ENV,
|
|
2016
|
+
DASHBOARD_PROTECTION_CHECK,
|
|
3027
2017
|
DashboardService,
|
|
3028
2018
|
DurableApiController,
|
|
2019
|
+
DurableApiControllerBase,
|
|
3029
2020
|
DurableApiModule,
|
|
3030
|
-
DurableApiSessionGuard,
|
|
3031
|
-
DurableAuthController,
|
|
3032
|
-
DurableDashboardGateGuard,
|
|
3033
2021
|
DurableDashboardModule,
|
|
3034
2022
|
DurableUiController,
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
readDashboardToken,
|
|
3038
|
-
reportDashboardGate,
|
|
3039
|
-
resolveDashboardGate
|
|
2023
|
+
DurableUiControllerBase,
|
|
2024
|
+
UNPROTECTED_CONSOLE_IN_PRODUCTION
|
|
3040
2025
|
});
|
|
3041
2026
|
//# sourceMappingURL=index.cjs.map
|