@adonis-agora/agent-dashboard 0.5.0 → 0.6.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/CHANGELOG.md +10 -0
- package/README.md +15 -1
- package/dist/providers/agent_dashboard_provider.d.ts +10 -0
- package/dist/providers/agent_dashboard_provider.d.ts.map +1 -1
- package/dist/providers/agent_dashboard_provider.js +11 -3
- package/dist/providers/agent_dashboard_provider.js.map +1 -1
- package/package.json +14 -13
- package/dist/src/server/define_config.d.ts +0 -69
- package/dist/src/server/define_config.d.ts.map +0 -1
- package/dist/src/server/define_config.js +0 -56
- package/dist/src/server/define_config.js.map +0 -1
- package/dist/src/server/gate.d.ts +0 -33
- package/dist/src/server/gate.d.ts.map +0 -1
- package/dist/src/server/gate.js +0 -52
- package/dist/src/server/gate.js.map +0 -1
- package/dist/src/server/paths.d.ts +0 -35
- package/dist/src/server/paths.d.ts.map +0 -1
- package/dist/src/server/paths.js +0 -94
- package/dist/src/server/paths.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @adonis-agora/agent-dashboard
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`58783fb`](https://github.com/DavideCarvalho/adonis-agora-agent/commit/58783fb433fd3c641dc9a42b80eaba09f2c9a62b) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - `@adonis-agora/agent` now ships its own governance dashboard — `node ace configure @adonis-agora/agent` registers an embedded `dashboard_provider` that serves the `@adonis-agora/agent-dashboard` SPA straight out of `@adonis-agora/agent`'s own build (`../dashboard/dist/spa` is copied into `dist/assets/spa` at build time), so a new app needs no separate install or provider registration to get the console. Configure it via the same optional `config('agent').dashboard` block as before.
|
|
8
|
+
|
|
9
|
+
This is purely additive: the standalone `@adonis-agora/agent-dashboard` package and its own `agent_dashboard_provider` keep working exactly as before for apps that already install and register it directly — both providers now share one implementation (`@adonis-agora/agent/dashboard`, a new subpath export) so their behavior is byte-for-byte identical. Register only one of the two in a given app; mounting both at the same path throws AdonisJS's "duplicate route" error at boot.
|
|
10
|
+
|
|
11
|
+
`@adonis-agora/agent-dashboard`'s peer dependency floor on `@adonis-agora/agent` moves to `>=0.21.0` (the version that introduces the shared `@adonis-agora/agent/dashboard` export its provider now imports from); already-published `agent-dashboard` versions are unaffected.
|
|
12
|
+
|
|
3
13
|
## 0.5.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -20,7 +20,17 @@ All data comes from the agent provider's **real** routes — the SPA is a pure c
|
|
|
20
20
|
|
|
21
21
|
## Install
|
|
22
22
|
|
|
23
|
+
As of `@adonis-agora/agent@0.21.0`, **you don't need to install this package at all**:
|
|
24
|
+
`node ace configure @adonis-agora/agent` registers an embedded dashboard provider that serves this
|
|
25
|
+
exact SPA (bundled straight into `@adonis-agora/agent`'s own `dist/` at build time) at
|
|
26
|
+
`<agentPath>/dashboard` — no separate install, no separate provider registration. See the
|
|
27
|
+
[`@adonis-agora/agent` README's Dashboard section](../adonis/README.md#dashboard).
|
|
28
|
+
|
|
29
|
+
This package still ships and installs standalone, for apps that configured it before the embedded
|
|
30
|
+
provider existed, or that want its independent release cadence:
|
|
31
|
+
|
|
23
32
|
```sh
|
|
33
|
+
pnpm add @adonis-agora/agent-dashboard
|
|
24
34
|
node ace add @adonis-agora/agent-dashboard
|
|
25
35
|
```
|
|
26
36
|
|
|
@@ -35,7 +45,8 @@ providers: [
|
|
|
35
45
|
|
|
36
46
|
The dashboard reads `config/agent.ts` for the agent `path` and `actorResolver`, mounts the SPA at
|
|
37
47
|
`<agentPath>/dashboard` (default `/agent/dashboard`), and gates every request through the **same**
|
|
38
|
-
actor resolver as the governance routes. Toggle or relocate it with an optional block
|
|
48
|
+
actor resolver as the governance routes. Toggle or relocate it with an optional block — the SAME block
|
|
49
|
+
the embedded provider reads, so switching between the two needs no config change:
|
|
39
50
|
|
|
40
51
|
```ts
|
|
41
52
|
// config/agent.ts
|
|
@@ -45,6 +56,9 @@ export default defineConfig({
|
|
|
45
56
|
})
|
|
46
57
|
```
|
|
47
58
|
|
|
59
|
+
Register only ONE of the two providers (the embedded one from `@adonis-agora/agent`, or this
|
|
60
|
+
package's): mounting both at the same path throws AdonisJS's "duplicate route" error at boot.
|
|
61
|
+
|
|
48
62
|
## Browser client
|
|
49
63
|
|
|
50
64
|
The framework-free fetch client is exported for reuse:
|
|
@@ -17,6 +17,16 @@ import type { ApplicationService } from '@adonisjs/core/types';
|
|
|
17
17
|
* every panel but Quota. The provider declines and logs why (see `decideDashboardMount`).
|
|
18
18
|
*
|
|
19
19
|
* Enable/disable and override the mount via the optional `config('agent').dashboard` block.
|
|
20
|
+
*
|
|
21
|
+
* As of `@adonis-agora/agent@0.21.0`, THIS is no longer the only way to get the console: the agent
|
|
22
|
+
* package now ALSO ships its own embedded `@adonis-agora/agent/dashboard_provider`, wired
|
|
23
|
+
* automatically by `node ace configure @adonis-agora/agent`, that serves the identical SPA bundled
|
|
24
|
+
* straight into `@adonis-agora/agent`'s own `dist/`. This standalone package keeps working exactly as
|
|
25
|
+
* before for apps that already install and register it directly — nothing here changed except WHERE
|
|
26
|
+
* the shared config/gate/path logic lives (`@adonis-agora/agent/dashboard`, imported above, rather
|
|
27
|
+
* than a local `src/server/*` copy) so both providers stay byte-for-byte identical in behavior. An
|
|
28
|
+
* app should register ONE of the two: registering both at the same mount path throws AdonisJS's
|
|
29
|
+
* "duplicate route" error at boot.
|
|
20
30
|
*/
|
|
21
31
|
export default class AgentDashboardProvider {
|
|
22
32
|
protected app: ApplicationService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent_dashboard_provider.d.ts","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent_dashboard_provider.d.ts","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IAC7B,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,+FAA+F;IAC/F,OAAO,CAAC,SAAS,CAAuC;IAElD,IAAI;IAsDV;;;;;OAKG;YACW,IAAI;IAalB;;;OAGG;YACW,SAAS;IAOvB,4FAA4F;YAC9E,SAAS;CAmBxB"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { decideDashboardMount, resolveDashboardConfig, } from '
|
|
3
|
-
import { evaluateDashboardGate } from '../src/server/gate.js';
|
|
4
|
-
import { apiBaseFor, contentTypeFor, injectApiBase, injectBaseHref, mountPathFor, safeAssetSegments, } from '../src/server/paths.js';
|
|
2
|
+
import { apiBaseFor, contentTypeFor, decideDashboardMount, evaluateDashboardGate, injectApiBase, injectBaseHref, mountPathFor, resolveDashboardConfig, safeAssetSegments, } from '@adonis-agora/agent/dashboard';
|
|
5
3
|
/**
|
|
6
4
|
* Serves the `@adonis-agora/agent-dashboard` governance SPA (a Vite build in `dist/spa`) as static
|
|
7
5
|
* assets under `<agentPath>/dashboard`, behind the SAME actor gating as the agent's governance
|
|
@@ -20,6 +18,16 @@ import { apiBaseFor, contentTypeFor, injectApiBase, injectBaseHref, mountPathFor
|
|
|
20
18
|
* every panel but Quota. The provider declines and logs why (see `decideDashboardMount`).
|
|
21
19
|
*
|
|
22
20
|
* Enable/disable and override the mount via the optional `config('agent').dashboard` block.
|
|
21
|
+
*
|
|
22
|
+
* As of `@adonis-agora/agent@0.21.0`, THIS is no longer the only way to get the console: the agent
|
|
23
|
+
* package now ALSO ships its own embedded `@adonis-agora/agent/dashboard_provider`, wired
|
|
24
|
+
* automatically by `node ace configure @adonis-agora/agent`, that serves the identical SPA bundled
|
|
25
|
+
* straight into `@adonis-agora/agent`'s own `dist/`. This standalone package keeps working exactly as
|
|
26
|
+
* before for apps that already install and register it directly — nothing here changed except WHERE
|
|
27
|
+
* the shared config/gate/path logic lives (`@adonis-agora/agent/dashboard`, imported above, rather
|
|
28
|
+
* than a local `src/server/*` copy) so both providers stay byte-for-byte identical in behavior. An
|
|
29
|
+
* app should register ONE of the two: registering both at the same mount path throws AdonisJS's
|
|
30
|
+
* "duplicate route" error at boot.
|
|
23
31
|
*/
|
|
24
32
|
export default class AgentDashboardProvider {
|
|
25
33
|
app;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent_dashboard_provider.js","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent_dashboard_provider.js","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonis-agora/agent-dashboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Read-only governance console (spend by model/actor, usage trend, recent threads & tool calls, quota) for @adonis-agora/agent — a dependency-light React SPA served by a thin AdonisJS provider. Part of the Agora ecosystem.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/DavideCarvalho/adonis-agent.git",
|
|
8
|
+
"url": "git+https://github.com/DavideCarvalho/adonis-agora-agent.git",
|
|
9
9
|
"directory": "packages/dashboard"
|
|
10
10
|
},
|
|
11
11
|
"author": "Davi Carvalho <davi@goflip.ai>",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"sideEffects": false,
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@adonisjs/core": "^7.3.0",
|
|
40
|
-
"@adonis-agora/agent": ">=0.
|
|
40
|
+
"@adonis-agora/agent": ">=0.21.0 <1.0.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependenciesMeta": {
|
|
43
43
|
"@adonisjs/core": {
|
|
@@ -46,21 +46,21 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@adonisjs/core": "7.4.0",
|
|
49
|
-
"@testing-library/react": "
|
|
50
|
-
"@types/node": "
|
|
49
|
+
"@testing-library/react": "16.3.2",
|
|
50
|
+
"@types/node": "22.20.0",
|
|
51
51
|
"@types/react": "19.2.18",
|
|
52
52
|
"@types/react-dom": "19.2.4",
|
|
53
|
-
"@vitejs/plugin-react": "
|
|
54
|
-
"jsdom": "
|
|
53
|
+
"@vitejs/plugin-react": "4.7.0",
|
|
54
|
+
"jsdom": "25.0.1",
|
|
55
55
|
"react": "19.2.8",
|
|
56
56
|
"react-dom": "19.2.8",
|
|
57
|
-
"typescript": "
|
|
58
|
-
"vite": "
|
|
59
|
-
"vitest": "
|
|
60
|
-
"@adonis-agora/agent": "0.
|
|
57
|
+
"typescript": "5.9.3",
|
|
58
|
+
"vite": "7.3.6",
|
|
59
|
+
"vitest": "3.2.7",
|
|
60
|
+
"@adonis-agora/agent": "0.21.0"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
|
-
"node": "
|
|
63
|
+
"node": "v26.7.0"
|
|
64
64
|
},
|
|
65
65
|
"keywords": [
|
|
66
66
|
"adonisjs",
|
|
@@ -76,7 +76,8 @@
|
|
|
76
76
|
"agora"
|
|
77
77
|
],
|
|
78
78
|
"scripts": {
|
|
79
|
-
"build": "pnpm run clean &&
|
|
79
|
+
"build": "pnpm run clean && pnpm run build:spa && tsc -p tsconfig.build.json && pnpm run check:dist",
|
|
80
|
+
"build:spa": "vite build",
|
|
80
81
|
"check:dist": "node ../../scripts/assert-build-output.mjs dist providers/agent_dashboard_provider.js",
|
|
81
82
|
"clean": "rm -rf dist",
|
|
82
83
|
"test": "vitest run --passWithNoTests",
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { Actor, AgentGovernanceAuthorize } from '@adonis-agora/agent';
|
|
2
|
-
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
-
/**
|
|
4
|
-
* An extra authorization gate for the dashboard, run AFTER the agent config's `actorResolver` has
|
|
5
|
-
* resolved the caller. Return `false` (or throw) to deny — the request gets `403`. The governance
|
|
6
|
-
* read-model the SPA serves spans EVERY actor's spend/usage, so most apps restrict the console beyond
|
|
7
|
-
* mere authentication, e.g. `(actor) => actor.roles?.includes('ADMIN') ?? false`.
|
|
8
|
-
*/
|
|
9
|
-
export type AgentDashboardAuthorize = (actor: Actor, ctx: HttpContext) => boolean | Promise<boolean>;
|
|
10
|
-
/**
|
|
11
|
-
* Optional `config('agent').dashboard` block. The dashboard reuses the agent config's `path` and
|
|
12
|
-
* `actorResolver` (so it sits behind the SAME actor gating as the governance routes); this block
|
|
13
|
-
* toggles it on/off, optionally overrides the mount path, and optionally adds an `authorize` gate.
|
|
14
|
-
*/
|
|
15
|
-
export interface AgentDashboardConfig {
|
|
16
|
-
/**
|
|
17
|
-
* Mount the SPA. Default `true` — set `false` to keep the routes off entirely. Note `true` is
|
|
18
|
-
* necessary but not sufficient: the console also needs the agent's `governanceAuthorize` gate, see
|
|
19
|
-
* {@link decideDashboardMount}.
|
|
20
|
-
*/
|
|
21
|
-
enabled?: boolean;
|
|
22
|
-
/** Override the mount path. Default `<agentPath>/dashboard`. */
|
|
23
|
-
path?: string;
|
|
24
|
-
/**
|
|
25
|
-
* Extra authorization run after the actor resolves. Return `false` to deny (`403`). Omit to allow
|
|
26
|
-
* any resolved actor (the default) — note this is only an EXTRA gate on the SPA shell; whether the
|
|
27
|
-
* console mounts at all, and whether its data is readable, is decided by the agent config's
|
|
28
|
-
* `governanceAuthorize`.
|
|
29
|
-
*/
|
|
30
|
-
authorize?: AgentDashboardAuthorize;
|
|
31
|
-
}
|
|
32
|
-
export interface ResolvedAgentDashboardConfig {
|
|
33
|
-
enabled: boolean;
|
|
34
|
-
path?: string;
|
|
35
|
-
authorize?: AgentDashboardAuthorize;
|
|
36
|
-
}
|
|
37
|
-
/** Fill defaults for the optional dashboard config block. */
|
|
38
|
-
export declare function resolveDashboardConfig(config: AgentDashboardConfig | undefined): ResolvedAgentDashboardConfig;
|
|
39
|
-
/** Whether the provider registers the console's routes, and (when it refuses) what to say about it. */
|
|
40
|
-
export type DashboardMountDecision = {
|
|
41
|
-
mount: true;
|
|
42
|
-
} | {
|
|
43
|
-
mount: false;
|
|
44
|
-
reason: 'disabled';
|
|
45
|
-
} | {
|
|
46
|
-
mount: false;
|
|
47
|
-
reason: 'no-governance-gate';
|
|
48
|
-
warning: string;
|
|
49
|
-
} | {
|
|
50
|
-
mount: false;
|
|
51
|
-
reason: 'no-governance-queries';
|
|
52
|
-
warning: string;
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* Decide whether to register the console's routes at all — the router-free core of the provider's
|
|
56
|
-
* mount check, extracted so it can be unit tested without booting an app.
|
|
57
|
-
*
|
|
58
|
-
* The console is a pure consumer of the agent's cross-actor `/agent/governance/*` read routes, and
|
|
59
|
-
* those routes are not mounted unless the agent config carries a `governanceAuthorize` gate. Serving
|
|
60
|
-
* a shell that can only 404 its own data is worse than not serving it: the failure shows up as seven
|
|
61
|
-
* dead panels at click time with nothing anywhere explaining why. So the console follows the same
|
|
62
|
-
* fail-closed-by-omission rule one layer down — no gate, no routes — and says so at boot.
|
|
63
|
-
*
|
|
64
|
-
* This costs nothing that still works: every app affected is an app whose console is ALREADY dead in
|
|
65
|
-
* every view but Quota. `dashboard.authorize` is deliberately NOT the trigger; it gates the shell,
|
|
66
|
-
* not the data, and an app can set it and still have a console with nothing to render.
|
|
67
|
-
*/
|
|
68
|
-
export declare function decideDashboardMount(enabled: boolean, governanceAuthorize: AgentGovernanceAuthorize | undefined, governanceQueries?: unknown): DashboardMountDecision;
|
|
69
|
-
//# sourceMappingURL=define_config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/server/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,WAAW,KACb,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAED,6DAA6D;AAC7D,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GACvC,4BAA4B,CAK9B;AAED,uGAAuG;AACvG,MAAM,MAAM,sBAAsB,GAC9B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAoBvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAE,wBAAwB,GAAG,SAAS,EACzD,iBAAiB,CAAC,EAAE,OAAO,GAC1B,sBAAsB,CAgBxB"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/** Fill defaults for the optional dashboard config block. */
|
|
2
|
-
export function resolveDashboardConfig(config) {
|
|
3
|
-
const resolved = { enabled: config?.enabled ?? true };
|
|
4
|
-
if (config?.path !== undefined)
|
|
5
|
-
resolved.path = config.path;
|
|
6
|
-
if (config?.authorize !== undefined)
|
|
7
|
-
resolved.authorize = config.authorize;
|
|
8
|
-
return resolved;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* The exact wording the provider logs when it declines to mount. Mirrors the agent provider's own
|
|
12
|
-
* governance boot warning — same three facts, same vocabulary — so a reader who sees one recognises
|
|
13
|
-
* the other.
|
|
14
|
-
*/
|
|
15
|
-
const NO_GOVERNANCE_GATE_WARNING = '[@adonis-agora/agent-dashboard] the governance console was NOT mounted: every panel but Quota reads the cross-actor `/agent/governance/*` routes, and those are themselves not mounted because no `governanceAuthorize` gate is configured — so the console would load and then fail on every panel. Set `governanceAuthorize` in config/agent.ts (e.g. an ADMIN check) to mount the routes and this console gated, or `governanceAuthorize: () => true` to deliberately restore the old behaviour of letting ANY authenticated actor read them. `GET /agent/approvals/mine` is unaffected — it stays mounted and scoped to the calling actor. To keep the console off on purpose and silence this, set `dashboard: { enabled: false }`.';
|
|
16
|
-
/**
|
|
17
|
-
* The wording logged when the read-model itself was turned off. Deliberately distinct from
|
|
18
|
-
* {@link NO_GOVERNANCE_GATE_WARNING}: both produce the same dead console, and an operator staring at
|
|
19
|
-
* a 404 must be able to tell from the log ALONE which of the two knobs is responsible. A shared
|
|
20
|
-
* "governance is not configured" message would recreate exactly the diagnosability problem this
|
|
21
|
-
* check exists to remove.
|
|
22
|
-
*/
|
|
23
|
-
const NO_GOVERNANCE_QUERIES_WARNING = '[@adonis-agora/agent-dashboard] the governance console was NOT mounted: `governanceQueries` is set to `false` in config/agent.ts, so the cross-actor read-model was never built and the `/agent/governance/*` routes it serves do not exist — the console would load and then fail on every panel but Quota. A `governanceAuthorize` gate is NOT the missing piece here; it is already configured. Remove `governanceQueries: false` (omit it to get the Lucid read-model when the main store is Lucid, or pass a store/factory explicitly) to mount the read-model and this console. To keep the console off on purpose and silence this, set `dashboard: { enabled: false }`.';
|
|
24
|
-
/**
|
|
25
|
-
* Decide whether to register the console's routes at all — the router-free core of the provider's
|
|
26
|
-
* mount check, extracted so it can be unit tested without booting an app.
|
|
27
|
-
*
|
|
28
|
-
* The console is a pure consumer of the agent's cross-actor `/agent/governance/*` read routes, and
|
|
29
|
-
* those routes are not mounted unless the agent config carries a `governanceAuthorize` gate. Serving
|
|
30
|
-
* a shell that can only 404 its own data is worse than not serving it: the failure shows up as seven
|
|
31
|
-
* dead panels at click time with nothing anywhere explaining why. So the console follows the same
|
|
32
|
-
* fail-closed-by-omission rule one layer down — no gate, no routes — and says so at boot.
|
|
33
|
-
*
|
|
34
|
-
* This costs nothing that still works: every app affected is an app whose console is ALREADY dead in
|
|
35
|
-
* every view but Quota. `dashboard.authorize` is deliberately NOT the trigger; it gates the shell,
|
|
36
|
-
* not the data, and an app can set it and still have a console with nothing to render.
|
|
37
|
-
*/
|
|
38
|
-
export function decideDashboardMount(enabled, governanceAuthorize, governanceQueries) {
|
|
39
|
-
if (!enabled)
|
|
40
|
-
return { mount: false, reason: 'disabled' };
|
|
41
|
-
if (governanceAuthorize === undefined) {
|
|
42
|
-
return { mount: false, reason: 'no-governance-gate', warning: NO_GOVERNANCE_GATE_WARNING };
|
|
43
|
-
}
|
|
44
|
-
// ONLY an explicit `false` is decidable here. `undefined` does NOT mean "no read-model": the agent
|
|
45
|
-
// provider's `#resolveGovernance` defaults it to the Lucid read-model whenever the main store is
|
|
46
|
-
// Lucid, and reproducing that resolution would duplicate provider logic in the dashboard.
|
|
47
|
-
if (governanceQueries === false) {
|
|
48
|
-
return {
|
|
49
|
-
mount: false,
|
|
50
|
-
reason: 'no-governance-queries',
|
|
51
|
-
warning: NO_GOVERNANCE_QUERIES_WARNING,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return { mount: true };
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=define_config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/server/define_config.ts"],"names":[],"mappings":"AA2CA,6DAA6D;AAC7D,MAAM,UAAU,sBAAsB,CACpC,MAAwC;IAExC,MAAM,QAAQ,GAAiC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC;IACpF,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAC5D,IAAI,MAAM,EAAE,SAAS,KAAK,SAAS;QAAE,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAC3E,OAAO,QAAQ,CAAC;AAClB,CAAC;AASD;;;;GAIG;AACH,MAAM,0BAA0B,GAC9B,0sBAA0sB,CAAC;AAE7sB;;;;;;GAMG;AACH,MAAM,6BAA6B,GACjC,ipBAAipB,CAAC;AAEppB;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAgB,EAChB,mBAAyD,EACzD,iBAA2B;IAE3B,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC1D,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;IAC7F,CAAC;IACD,mGAAmG;IACnG,iGAAiG;IACjG,0FAA0F;IAC1F,IAAI,iBAAiB,KAAK,KAAK,EAAE,CAAC;QAChC,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,uBAAuB;YAC/B,OAAO,EAAE,6BAA6B;SACvC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { ActorResolver } from '@adonis-agora/agent';
|
|
2
|
-
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
-
import type { AgentDashboardAuthorize } from './define_config.js';
|
|
4
|
-
/** The outcome of the dashboard access gate: proceed, or deny with an HTTP status + message. */
|
|
5
|
-
export type DashboardGateVerdict = {
|
|
6
|
-
ok: true;
|
|
7
|
-
} | {
|
|
8
|
-
ok: false;
|
|
9
|
-
status: 401 | 403;
|
|
10
|
-
error: string;
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Decide whether a request may reach the dashboard, WITHOUT touching the response — so it is unit
|
|
14
|
-
* testable free of the AdonisJS router/app: resolve the actor through the agent config's resolver
|
|
15
|
-
* (missing/failed → `401`), then run the optional `authorize` gate over the resolved actor
|
|
16
|
-
* (denied/threw → `403`).
|
|
17
|
-
*
|
|
18
|
-
* This gates the SPA **shell**, and only the shell. It is NOT what decides whether the console's data
|
|
19
|
-
* is readable, and it is no longer the last line of defence it once had to be:
|
|
20
|
-
*
|
|
21
|
-
* - Whether the console mounts at all is decided earlier, by {@link decideDashboardMount} — the
|
|
22
|
-
* routes are not registered unless the agent config carries a `governanceAuthorize` gate AND its
|
|
23
|
-
* `governanceQueries` read-model exists. So this function never runs for a console that could only
|
|
24
|
-
* 404 its own panels.
|
|
25
|
-
* - Whether the DATA is readable is decided by the agent's own `governanceAuthorize` on the
|
|
26
|
-
* `/agent/governance/*` routes, not here. Omitting `authorize` while a gate is configured leaves
|
|
27
|
-
* the shell open to any resolved actor but exposes no cross-actor data.
|
|
28
|
-
*
|
|
29
|
-
* Omitting BOTH the resolver and `authorize` would expose the shell to any request; the provider is
|
|
30
|
-
* expected to short-circuit on a missing resolver via the `401` here.
|
|
31
|
-
*/
|
|
32
|
-
export declare function evaluateDashboardGate(ctx: HttpContext, actorResolver: ActorResolver | undefined, authorize?: AgentDashboardAuthorize): Promise<DashboardGateVerdict>;
|
|
33
|
-
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../src/server/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,gGAAgG;AAChG,MAAM,MAAM,oBAAoB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,WAAW,EAChB,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,SAAS,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,oBAAoB,CAAC,CA4B/B"}
|
package/dist/src/server/gate.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decide whether a request may reach the dashboard, WITHOUT touching the response — so it is unit
|
|
3
|
-
* testable free of the AdonisJS router/app: resolve the actor through the agent config's resolver
|
|
4
|
-
* (missing/failed → `401`), then run the optional `authorize` gate over the resolved actor
|
|
5
|
-
* (denied/threw → `403`).
|
|
6
|
-
*
|
|
7
|
-
* This gates the SPA **shell**, and only the shell. It is NOT what decides whether the console's data
|
|
8
|
-
* is readable, and it is no longer the last line of defence it once had to be:
|
|
9
|
-
*
|
|
10
|
-
* - Whether the console mounts at all is decided earlier, by {@link decideDashboardMount} — the
|
|
11
|
-
* routes are not registered unless the agent config carries a `governanceAuthorize` gate AND its
|
|
12
|
-
* `governanceQueries` read-model exists. So this function never runs for a console that could only
|
|
13
|
-
* 404 its own panels.
|
|
14
|
-
* - Whether the DATA is readable is decided by the agent's own `governanceAuthorize` on the
|
|
15
|
-
* `/agent/governance/*` routes, not here. Omitting `authorize` while a gate is configured leaves
|
|
16
|
-
* the shell open to any resolved actor but exposes no cross-actor data.
|
|
17
|
-
*
|
|
18
|
-
* Omitting BOTH the resolver and `authorize` would expose the shell to any request; the provider is
|
|
19
|
-
* expected to short-circuit on a missing resolver via the `401` here.
|
|
20
|
-
*/
|
|
21
|
-
export async function evaluateDashboardGate(ctx, actorResolver, authorize) {
|
|
22
|
-
if (actorResolver === undefined) {
|
|
23
|
-
return { ok: false, status: 401, error: 'no actor resolver configured' };
|
|
24
|
-
}
|
|
25
|
-
let actor;
|
|
26
|
-
try {
|
|
27
|
-
actor = await actorResolver.resolve(ctx);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
return {
|
|
31
|
-
ok: false,
|
|
32
|
-
status: 401,
|
|
33
|
-
error: error instanceof Error ? error.message : 'unauthorized',
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
if (authorize !== undefined) {
|
|
37
|
-
try {
|
|
38
|
-
if (!(await authorize(actor, ctx))) {
|
|
39
|
-
return { ok: false, status: 403, error: 'forbidden' };
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
return {
|
|
44
|
-
ok: false,
|
|
45
|
-
status: 403,
|
|
46
|
-
error: error instanceof Error ? error.message : 'forbidden',
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return { ok: true };
|
|
51
|
-
}
|
|
52
|
-
//# sourceMappingURL=gate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../../src/server/gate.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAgB,EAChB,aAAwC,EACxC,SAAmC;IAEnC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC;IAC3E,CAAC;IACD,IAAI,KAAoD,CAAC;IACzD,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc;SAC/D,CAAC;IACJ,CAAC;IACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;gBACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YACxD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW;aAC5D,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure path/asset helpers for the dashboard provider — extracted so they can be unit-tested without
|
|
3
|
-
* booting an AdonisJS app. The provider composes these; it holds only the router wiring + I/O.
|
|
4
|
-
*/
|
|
5
|
-
/** Collapse duplicate slashes and strip leading/trailing ones: `/agent//` → `agent`. */
|
|
6
|
-
export declare function trimSlashes(path: string): string;
|
|
7
|
-
/** The agent API base as an absolute path with a single leading slash: `agent` → `/agent`. */
|
|
8
|
-
export declare function apiBaseFor(agentPath: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* The canonical dashboard mount path (no trailing slash), default `<agentPath>/dashboard`. A caller
|
|
11
|
-
* may override with an explicit `dashboardPath`; both are normalized to a single leading slash.
|
|
12
|
-
*/
|
|
13
|
-
export declare function mountPathFor(agentPath: string, dashboardPath?: string): string;
|
|
14
|
-
/** MIME type for a filename by extension; `application/octet-stream` for anything unknown. */
|
|
15
|
-
export declare function contentTypeFor(filename: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Reject a wildcard asset request that tries to escape the SPA root via `..` or an absolute path.
|
|
18
|
-
* Returns the safe, normalized relative segments (never starting with `..`), or `null` to deny.
|
|
19
|
-
*/
|
|
20
|
-
export declare function safeAssetSegments(wildcard: string | string[] | undefined): string[] | null;
|
|
21
|
-
/**
|
|
22
|
-
* Inject the resolved agent API base into the served `index.html` as a global the SPA reads before
|
|
23
|
-
* boot, so the client calls the exact base the provider mounted (no build-time coupling). Idempotent
|
|
24
|
-
* per response — inserted right before `</head>`.
|
|
25
|
-
*/
|
|
26
|
-
export declare function injectApiBase(html: string, apiBase: string): string;
|
|
27
|
-
/**
|
|
28
|
-
* Inject a `<base href="${mount}/">` as the FIRST thing inside `<head>`, so the SPA's relative
|
|
29
|
-
* `./assets/*` URLs (Vite `base: './'`) resolve against the mount directory no matter whether the
|
|
30
|
-
* browser's URL carries a trailing slash. This replaces the old trailing-slash redirect, which the
|
|
31
|
-
* AdonisJS router (it normalizes trailing slashes) turned into a duplicate-route crash. `mount` is a
|
|
32
|
-
* leading-slash, no-trailing-slash path (e.g. `/agent/dashboard`).
|
|
33
|
-
*/
|
|
34
|
-
export declare function injectBaseHref(html: string, mount: string): string;
|
|
35
|
-
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/server/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAM9E;AAsBD,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,IAAI,CAU1F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAInE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlE"}
|
package/dist/src/server/paths.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure path/asset helpers for the dashboard provider — extracted so they can be unit-tested without
|
|
3
|
-
* booting an AdonisJS app. The provider composes these; it holds only the router wiring + I/O.
|
|
4
|
-
*/
|
|
5
|
-
/** Collapse duplicate slashes and strip leading/trailing ones: `/agent//` → `agent`. */
|
|
6
|
-
export function trimSlashes(path) {
|
|
7
|
-
return path.replace(/\/+/g, '/').replace(/^\/+|\/+$/g, '');
|
|
8
|
-
}
|
|
9
|
-
/** The agent API base as an absolute path with a single leading slash: `agent` → `/agent`. */
|
|
10
|
-
export function apiBaseFor(agentPath) {
|
|
11
|
-
const trimmed = trimSlashes(agentPath);
|
|
12
|
-
return trimmed === '' ? '/' : `/${trimmed}`;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* The canonical dashboard mount path (no trailing slash), default `<agentPath>/dashboard`. A caller
|
|
16
|
-
* may override with an explicit `dashboardPath`; both are normalized to a single leading slash.
|
|
17
|
-
*/
|
|
18
|
-
export function mountPathFor(agentPath, dashboardPath) {
|
|
19
|
-
if (dashboardPath !== undefined && trimSlashes(dashboardPath) !== '') {
|
|
20
|
-
return `/${trimSlashes(dashboardPath)}`;
|
|
21
|
-
}
|
|
22
|
-
const trimmed = trimSlashes(agentPath);
|
|
23
|
-
return trimmed === '' ? '/dashboard' : `/${trimmed}/dashboard`;
|
|
24
|
-
}
|
|
25
|
-
const CONTENT_TYPES = {
|
|
26
|
-
html: 'text/html; charset=utf-8',
|
|
27
|
-
js: 'text/javascript; charset=utf-8',
|
|
28
|
-
mjs: 'text/javascript; charset=utf-8',
|
|
29
|
-
css: 'text/css; charset=utf-8',
|
|
30
|
-
json: 'application/json; charset=utf-8',
|
|
31
|
-
svg: 'image/svg+xml',
|
|
32
|
-
png: 'image/png',
|
|
33
|
-
jpg: 'image/jpeg',
|
|
34
|
-
jpeg: 'image/jpeg',
|
|
35
|
-
gif: 'image/gif',
|
|
36
|
-
webp: 'image/webp',
|
|
37
|
-
ico: 'image/x-icon',
|
|
38
|
-
woff: 'font/woff',
|
|
39
|
-
woff2: 'font/woff2',
|
|
40
|
-
ttf: 'font/ttf',
|
|
41
|
-
map: 'application/json; charset=utf-8',
|
|
42
|
-
txt: 'text/plain; charset=utf-8',
|
|
43
|
-
};
|
|
44
|
-
/** MIME type for a filename by extension; `application/octet-stream` for anything unknown. */
|
|
45
|
-
export function contentTypeFor(filename) {
|
|
46
|
-
const dot = filename.lastIndexOf('.');
|
|
47
|
-
const ext = dot === -1 ? '' : filename.slice(dot + 1).toLowerCase();
|
|
48
|
-
return CONTENT_TYPES[ext] ?? 'application/octet-stream';
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Reject a wildcard asset request that tries to escape the SPA root via `..` or an absolute path.
|
|
52
|
-
* Returns the safe, normalized relative segments (never starting with `..`), or `null` to deny.
|
|
53
|
-
*/
|
|
54
|
-
export function safeAssetSegments(wildcard) {
|
|
55
|
-
const parts = Array.isArray(wildcard) ? wildcard : (wildcard ?? '').split('/');
|
|
56
|
-
const segments = [];
|
|
57
|
-
for (const raw of parts) {
|
|
58
|
-
const part = raw.trim();
|
|
59
|
-
if (part === '' || part === '.')
|
|
60
|
-
continue;
|
|
61
|
-
if (part === '..' || part.includes('\0') || part.includes('\\'))
|
|
62
|
-
return null;
|
|
63
|
-
segments.push(part);
|
|
64
|
-
}
|
|
65
|
-
return segments;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Inject the resolved agent API base into the served `index.html` as a global the SPA reads before
|
|
69
|
-
* boot, so the client calls the exact base the provider mounted (no build-time coupling). Idempotent
|
|
70
|
-
* per response — inserted right before `</head>`.
|
|
71
|
-
*/
|
|
72
|
-
export function injectApiBase(html, apiBase) {
|
|
73
|
-
const tag = `<script>window.__AGENT_DASHBOARD_BASE__=${JSON.stringify(apiBase)}</script>`;
|
|
74
|
-
if (html.includes('</head>'))
|
|
75
|
-
return html.replace('</head>', `${tag}</head>`);
|
|
76
|
-
return `${tag}${html}`;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Inject a `<base href="${mount}/">` as the FIRST thing inside `<head>`, so the SPA's relative
|
|
80
|
-
* `./assets/*` URLs (Vite `base: './'`) resolve against the mount directory no matter whether the
|
|
81
|
-
* browser's URL carries a trailing slash. This replaces the old trailing-slash redirect, which the
|
|
82
|
-
* AdonisJS router (it normalizes trailing slashes) turned into a duplicate-route crash. `mount` is a
|
|
83
|
-
* leading-slash, no-trailing-slash path (e.g. `/agent/dashboard`).
|
|
84
|
-
*/
|
|
85
|
-
export function injectBaseHref(html, mount) {
|
|
86
|
-
const tag = `<base href="${mount}/">`;
|
|
87
|
-
const headOpen = html.match(/<head[^>]*>/i);
|
|
88
|
-
if (headOpen?.index !== undefined) {
|
|
89
|
-
const at = headOpen.index + headOpen[0].length;
|
|
90
|
-
return html.slice(0, at) + tag + html.slice(at);
|
|
91
|
-
}
|
|
92
|
-
return `${tag}${html}`;
|
|
93
|
-
}
|
|
94
|
-
//# sourceMappingURL=paths.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/server/paths.ts"],"names":[],"mappings":"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"}
|