@eventcatalog/core 4.12.0-beta.9 → 4.12.1
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/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-GNFKUOXD.js → chunk-DZZDBFUM.js} +1 -1
- package/dist/{chunk-K3DWGBGQ.js → chunk-EVXNBTRA.js} +1 -1
- package/dist/{chunk-YOIPWS7L.js → chunk-HH6GPY4H.js} +1 -1
- package/dist/{chunk-UIHG2TPV.js → chunk-HHZFKWX7.js} +1 -1
- package/dist/{chunk-4S47JELQ.js → chunk-UWSBZYF5.js} +3 -3
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/docs/development/01-getting-started/develop-and-build.md +18 -0
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/02-configuration.md +4 -0
- package/dist/docs/development/components/components/27-code-group.md +95 -0
- package/dist/docs/development/components/components/28-columns.md +115 -0
- package/dist/docs/development/customization/05-custom-pages-and-api-routes/02-create-a-custom-page.md +21 -0
- package/dist/docs/development/customization/05-custom-pages-and-api-routes/04-reference.md +24 -0
- package/dist/docs/development/deployment/hosting-options.md +8 -0
- package/dist/docs/development/guides/resources/messages/09-add-usage-examples.md +103 -9
- package/dist/docs/development/guides/resources/schemas/04-explore-schemas/01-schema-explorer.md +79 -13
- package/dist/docs/development/upgrading/upgrading.md +8 -3
- package/dist/docs/development/upgrading/v4.md +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +12 -12
- package/dist/federation/federate.js +3 -3
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/runtime-dependencies/manifest.json +1 -3
- package/dist/runtime-dependencies/set-cookie-parser.mjs +3 -0
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/auth.config.ts +3 -4
- package/eventcatalog/src/components/Header.astro +101 -33
- package/eventcatalog/src/enterprise/auth/[...auth].ts +1 -1
- package/eventcatalog/src/enterprise/auth/login.astro +2 -2
- package/eventcatalog/src/enterprise/auth/middleware/middleware-auth.ts +1 -1
- package/eventcatalog/src/utils/auth-astro/client.ts +89 -0
- package/eventcatalog/src/utils/auth-astro/config.ts +24 -0
- package/eventcatalog/src/utils/auth-astro/server.ts +74 -0
- package/package.json +3 -2
- package/dist/runtime-dependencies/auth-astro.mjs +0 -3
- package/dist/runtime-dependencies/auth-astro__client.mjs +0 -3
- package/dist/runtime-dependencies/auth-astro__server.mjs +0 -3
- package/dist/{chunk-U4YJSTGV.js → chunk-WRLNLWPW.js} +7 -7
package/dist/docs/development/guides/resources/schemas/04-explore-schemas/01-schema-explorer.md
CHANGED
|
@@ -11,21 +11,22 @@ import AddedIn from '@site/src/components/MDX/AddedIn';
|
|
|
11
11
|
|
|
12
12
|
The Schema Explorer lets your teams quickly find the schema, understand who owns it, and who is producing or consuming it (see [demo](https://demo.eventcatalog.dev/schemas)).
|
|
13
13
|
|
|
14
|
-

|
|
15
15
|
|
|
16
16
|
Using the Schema Explorer, you can:
|
|
17
17
|
|
|
18
18
|
- Quickly find schemas in your Architecture
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
19
|
+
- Read usage examples written by the team that owns the schema
|
|
20
|
+
- See who is producing or consuming a schema, and which flows it is part of
|
|
21
|
+
- Compare versions of your schemas
|
|
22
|
+
- See schema ownership and where the schema comes from
|
|
22
23
|
- Get API (GET) access to your schemas for mocking or testing
|
|
23
24
|
|
|
24
25
|
### How to use the Schema Explorer?
|
|
25
26
|
|
|
26
27
|
You can access the Schema Explorer from the sidebar, or by going to the `/schemas/explorer` page.
|
|
27
28
|
|
|
28
|
-
The page will take all the schemas from your EventCatalog and render them in a searchable list.
|
|
29
|
+
The page will take all the schemas from your EventCatalog and render them in a searchable list. Select a schema to open it on the right.
|
|
29
30
|
|
|
30
31
|
:::tip Schema Path
|
|
31
32
|
You need to set the `schemaPath` in your schema frontmatter to the path to your schema file for Events, Queries and Commands.
|
|
@@ -33,19 +34,84 @@ You need to set the `schemaPath` in your schema frontmatter to the path to your
|
|
|
33
34
|
For services you need to specify the path to your specification file in the `specifications` frontmatter.
|
|
34
35
|
:::
|
|
35
36
|
|
|
36
|
-

|
|
37
|
-
|
|
38
37
|
##### Filters
|
|
39
|
-
You can use the filters to quickly find schemas in your Architecture. You can filter by name, message type and schema format.
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
Use the search box to find schemas by name. Select the filter button next to it to filter by type (events, commands, queries, or specifications) and by schema format.
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
<img src={require('../img/schema-explorer-2.png').default} alt="Schema Explorer search box and filters for type and format" style={{ width: '100%', maxWidth: '360px' }} />
|
|
44
42
|
|
|
45
|
-
#####
|
|
43
|
+
##### Schema pages
|
|
44
|
+
|
|
45
|
+
Every message schema also has its own page at `/schemas/{type}/{id}/{version}`, for example `/schemas/events/OrderCreated/1.0.0`. Share this link when you want someone to look at one schema.
|
|
46
|
+
|
|
47
|
+
### Schema tabs
|
|
48
|
+
|
|
49
|
+
<AddedIn version="4.11.0" />
|
|
50
|
+
|
|
51
|
+
Each schema is split into tabs. EventCatalog only shows a tab when there is something to show, for example the **Flows** tab only appears when the message is part of a flow.
|
|
52
|
+
|
|
53
|
+
| Tab | What it shows |
|
|
54
|
+
| --- | ------------- |
|
|
55
|
+
| **Schema** | The raw schema, with syntax highlighting and a copy button. |
|
|
56
|
+
| **Properties** | A readable view of the schema properties (JSON Schema, Avro and Protobuf). |
|
|
57
|
+
| **Examples** | [Usage examples](/docs/development/guides/resources/messages/add-usage-examples) stored in the message's `examples/` folder. |
|
|
58
|
+
| **Producers & Consumers** | A graph of the services that produce and consume the message. |
|
|
59
|
+
| **Flows** | The [flows](/docs/development/guides/resources/flows/introduction) the message is part of. |
|
|
60
|
+
| **Versions** | Every version of the schema, with a side-by-side comparison. |
|
|
61
|
+
| **Details** | Schema metadata: format, version, file, source, and owners. |
|
|
62
|
+
| **API** | API access to the schema (EventCatalog Scale). |
|
|
63
|
+
|
|
64
|
+
##### Link to a tab
|
|
65
|
+
|
|
66
|
+
The selected tab is stored in the `tab` query parameter, so you can link straight to it.
|
|
67
|
+
|
|
68
|
+
```txt
|
|
69
|
+
/schemas/events/OrderCreated/1.0.0?tab=examples
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| Tab | `tab` value |
|
|
73
|
+
| --- | ----------- |
|
|
74
|
+
| Schema | `schema` (default) |
|
|
75
|
+
| Properties | `properties` |
|
|
76
|
+
| Examples | `examples` |
|
|
77
|
+
| Producers & Consumers | `producers-consumers` |
|
|
78
|
+
| Flows | `flows` |
|
|
79
|
+
| Versions | `versions` |
|
|
80
|
+
| Details | `details` |
|
|
81
|
+
| API | `api` |
|
|
82
|
+
|
|
83
|
+
If the tab does not exist for that message, EventCatalog opens the **Schema** tab.
|
|
84
|
+
|
|
85
|
+
##### Examples
|
|
86
|
+
|
|
87
|
+
The **Examples** tab shows the examples your team has written for the message. Examples written in Markdown or MDX can explain the scenario and show code in several languages.
|
|
46
88
|
|
|
47
|
-
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
To add examples, see [Add usage examples](/docs/development/guides/resources/messages/add-usage-examples).
|
|
48
92
|
|
|
49
93
|
##### Producers and Consumers
|
|
50
94
|
|
|
51
|
-
The
|
|
95
|
+
The **Producers & Consumers** tab shows the services that produce and consume the message, using the same graph as the message page. Click on a producer or consumer to see more information about them.
|
|
96
|
+
|
|
97
|
+

|
|
98
|
+
|
|
99
|
+
##### Flows
|
|
100
|
+
|
|
101
|
+
The **Flows** tab shows the flows the message is part of. If the message is used in more than one flow, pick the flow from the dropdown. Use **Open flow** to go to the flow page.
|
|
102
|
+
|
|
103
|
+

|
|
104
|
+
|
|
105
|
+
##### Versions
|
|
106
|
+
|
|
107
|
+
The **Versions** tab lists every version of the schema. Select a version to view it, or pick a **From** and **To** version to compare them side by side. Use **Expand** to open the comparison in a larger view.
|
|
108
|
+
|
|
109
|
+
You can also switch versions from the version dropdown next to the schema name.
|
|
110
|
+
|
|
111
|
+
##### Details
|
|
112
|
+
|
|
113
|
+
The **Details** tab shows the schema name, format, message type, version, file, and owners. When a schema comes from an external source, the tab also shows where it came from.
|
|
114
|
+
|
|
115
|
+
##### API Access
|
|
116
|
+
|
|
117
|
+
For EventCatalog Scale users, you can get API (GET) access to your schemas for mocking or testing. See [Schema API](/docs/development/guides/resources/schemas/schema-api).
|
|
@@ -38,7 +38,11 @@ To upgrade your EventCatalog you can find the packages `@eventcatalog/core` your
|
|
|
38
38
|
Once you upgrade the version number, run `npm install` to install the latest updates.
|
|
39
39
|
|
|
40
40
|
:::tip
|
|
41
|
-
If you don't see the changes you expect, try removing the `.eventcatalog-core` folder
|
|
41
|
+
If you don't see the changes you expect, try removing the `.astro` folder, the `.eventcatalog-core` folder (if your project has one) and the `node_modules` folder, then install fresh again.
|
|
42
|
+
:::
|
|
43
|
+
|
|
44
|
+
:::info
|
|
45
|
+
From EventCatalog 4.12, EventCatalog no longer creates a `.eventcatalog-core` folder. If your project still has one from an older version, you can delete it once any older EventCatalog processes have stopped.
|
|
42
46
|
:::
|
|
43
47
|
|
|
44
48
|
### Having problems?
|
|
@@ -46,9 +50,10 @@ If you don't see the changes you expect, try removing the `.eventcatalog-core` f
|
|
|
46
50
|
Trying to upgrade and having issues? Try these steps
|
|
47
51
|
|
|
48
52
|
1. Delete `node_modules` folder
|
|
49
|
-
1. Delete `.
|
|
53
|
+
1. Delete `.astro` folder
|
|
54
|
+
1. Delete `.eventcatalog-core` folder (if you have one)
|
|
50
55
|
1. Delete `package-lock.json` (if you have one).
|
|
51
|
-
1. Run `npm
|
|
56
|
+
1. Run `npm install`
|
|
52
57
|
1. Verify if issues are fixed
|
|
53
58
|
|
|
54
59
|
Still having issues?
|
|
@@ -43,7 +43,7 @@ Before upgrading, we recommend:
|
|
|
43
43
|
|
|
44
44
|
1. Create a branch for the upgrade.
|
|
45
45
|
1. Upgrade `@eventcatalog/core`.
|
|
46
|
-
1. Remove `.eventcatalog-core
|
|
46
|
+
1. Remove `.astro`, `.eventcatalog-core` (if you have one), `node_modules`, and your lock file if the catalog does not pick up the new version.
|
|
47
47
|
1. Run your catalog locally and check custom pages, custom navigation, and visualiser links.
|
|
48
48
|
|
|
49
49
|
## Removed
|
package/dist/eventcatalog.cjs
CHANGED
|
@@ -181,7 +181,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
|
|
|
181
181
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
182
182
|
|
|
183
183
|
// package.json
|
|
184
|
-
var version = "4.12.
|
|
184
|
+
var version = "4.12.1";
|
|
185
185
|
|
|
186
186
|
// src/constants.ts
|
|
187
187
|
var VERSION = version;
|
package/dist/eventcatalog.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UWSBZYF5.js";
|
|
4
|
+
import "./chunk-HH6GPY4H.js";
|
|
4
5
|
import "./chunk-ZAZHAVKB.js";
|
|
5
6
|
import {
|
|
6
7
|
runMigrations
|
|
@@ -10,18 +11,17 @@ import {
|
|
|
10
11
|
FederationConflictError,
|
|
11
12
|
FederationDiagnosticError,
|
|
12
13
|
federateCatalog
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-WRNH5C3U.js";
|
|
15
|
-
import "./chunk-5EPNFDT5.js";
|
|
16
|
-
import "./chunk-A2RZR3U4.js";
|
|
17
|
-
import "./chunk-SDZQJTJW.js";
|
|
18
|
-
import "./chunk-352FGP6W.js";
|
|
19
|
-
import "./chunk-R7Z5ALYI.js";
|
|
14
|
+
} from "./chunk-WRLNLWPW.js";
|
|
20
15
|
import {
|
|
21
16
|
getFederationDiagnosticCounts,
|
|
22
17
|
getVisibleFederationDiagnostics
|
|
23
18
|
} from "./chunk-JJPB6EOZ.js";
|
|
24
19
|
import "./chunk-FV56YFM4.js";
|
|
20
|
+
import "./chunk-WRNH5C3U.js";
|
|
21
|
+
import "./chunk-5EPNFDT5.js";
|
|
22
|
+
import "./chunk-A2RZR3U4.js";
|
|
23
|
+
import "./chunk-SDZQJTJW.js";
|
|
24
|
+
import "./chunk-352FGP6W.js";
|
|
25
25
|
import {
|
|
26
26
|
getProjectOutDir,
|
|
27
27
|
isAuthEnabled,
|
|
@@ -30,10 +30,10 @@ import {
|
|
|
30
30
|
} from "./chunk-MDWB5HLO.js";
|
|
31
31
|
import {
|
|
32
32
|
generate
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-EVXNBTRA.js";
|
|
34
34
|
import {
|
|
35
35
|
logger
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-DZZDBFUM.js";
|
|
37
37
|
import {
|
|
38
38
|
resolve_catalog_dependencies_default
|
|
39
39
|
} from "./chunk-36RYTYT5.js";
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
import {
|
|
48
48
|
watch
|
|
49
49
|
} from "./chunk-U63GDPPY.js";
|
|
50
|
-
import "./chunk-
|
|
50
|
+
import "./chunk-R7Z5ALYI.js";
|
|
51
51
|
import {
|
|
52
52
|
getAstroConfigPath
|
|
53
53
|
} from "./chunk-VIJJ7JKH.js";
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
} from "./chunk-LFQJXLHG.js";
|
|
64
64
|
import {
|
|
65
65
|
VERSION
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-HHZFKWX7.js";
|
|
67
67
|
import {
|
|
68
68
|
getEventCatalogConfigFile,
|
|
69
69
|
verifyRequiredFieldsAreInCatalogConfigFile
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
FederationConflictError,
|
|
3
3
|
FederationDiagnosticError,
|
|
4
4
|
federateCatalog
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-WRLNLWPW.js";
|
|
6
|
+
import "../chunk-JJPB6EOZ.js";
|
|
7
|
+
import "../chunk-FV56YFM4.js";
|
|
6
8
|
import "../chunk-WRNH5C3U.js";
|
|
7
9
|
import "../chunk-5EPNFDT5.js";
|
|
8
10
|
import "../chunk-A2RZR3U4.js";
|
|
9
11
|
import "../chunk-SDZQJTJW.js";
|
|
10
12
|
import "../chunk-352FGP6W.js";
|
|
11
13
|
import "../chunk-R7Z5ALYI.js";
|
|
12
|
-
import "../chunk-JJPB6EOZ.js";
|
|
13
|
-
import "../chunk-FV56YFM4.js";
|
|
14
14
|
import "../chunk-RFIXKATC.js";
|
|
15
15
|
export {
|
|
16
16
|
FederationConflictError,
|
package/dist/generate.cjs
CHANGED
|
@@ -112,7 +112,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
|
|
|
112
112
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
113
113
|
|
|
114
114
|
// package.json
|
|
115
|
-
var version = "4.12.
|
|
115
|
+
var version = "4.12.1";
|
|
116
116
|
|
|
117
117
|
// src/constants.ts
|
|
118
118
|
var VERSION = version;
|
package/dist/generate.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generate
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-EVXNBTRA.js";
|
|
4
|
+
import "./chunk-DZZDBFUM.js";
|
|
5
|
+
import "./chunk-HHZFKWX7.js";
|
|
6
6
|
import "./chunk-RFIXKATC.js";
|
|
7
7
|
export {
|
|
8
8
|
generate
|
|
@@ -65,9 +65,6 @@
|
|
|
65
65
|
"astro/logger/node": "astro__logger__node.mjs",
|
|
66
66
|
"astro/types": "astro__types.mjs",
|
|
67
67
|
"astro/zod": "astro__zod.mjs",
|
|
68
|
-
"auth-astro": "auth-astro.mjs",
|
|
69
|
-
"auth-astro/client": "auth-astro__client.mjs",
|
|
70
|
-
"auth-astro/server": "auth-astro__server.mjs",
|
|
71
68
|
"boxen": "boxen.mjs",
|
|
72
69
|
"commander": "commander.mjs",
|
|
73
70
|
"cross-env": "cross-env.mjs",
|
|
@@ -123,6 +120,7 @@
|
|
|
123
120
|
"remark-gfm": "remark-gfm.mjs",
|
|
124
121
|
"rimraf": "rimraf.mjs",
|
|
125
122
|
"semver": "semver.mjs",
|
|
123
|
+
"set-cookie-parser": "set-cookie-parser.mjs",
|
|
126
124
|
"shelljs": "shelljs.mjs",
|
|
127
125
|
"sonner": "sonner.mjs",
|
|
128
126
|
"sql.js": "sql.js.mjs",
|
package/dist/utils/cli-logger.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineConfig } from 'auth-astro';
|
|
1
|
+
import { defineConfig } from '@utils/auth-astro/config';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import GitHub from '@auth/core/providers/github';
|
|
4
4
|
import Okta from '@auth/core/providers/okta';
|
|
@@ -22,9 +22,8 @@ const getAuthProviders = async () => {
|
|
|
22
22
|
// GitHub provider
|
|
23
23
|
if (authConfig.providers?.github) {
|
|
24
24
|
const githubConfig = authConfig.providers.github;
|
|
25
|
-
// GitHub sends an RFC 9207 `iss` parameter on OAuth callbacks. Pin the issuer
|
|
26
|
-
//
|
|
27
|
-
// default (auth-astro's peer range can hoist an older @auth/core in user projects).
|
|
25
|
+
// GitHub sends an RFC 9207 `iss` parameter on OAuth callbacks. Pin the issuer,
|
|
26
|
+
// including for GitHub Enterprise base URLs, so validation works.
|
|
28
27
|
const githubBaseUrl = githubConfig?.enterprise?.baseUrl ?? 'https://github.com';
|
|
29
28
|
providers.push(
|
|
30
29
|
GitHub({
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
isEventCatalogChatVisible,
|
|
9
9
|
isEventCatalogChatEnabled,
|
|
10
10
|
} from '@utils/feature';
|
|
11
|
-
import { getSession } from 'auth-astro/server';
|
|
11
|
+
import { getSession } from '@utils/auth-astro/server';
|
|
12
12
|
import { isAuthEnabled, isSSR } from '@utils/feature';
|
|
13
13
|
import { EnvironmentDropdown } from './EnvironmentDropdown';
|
|
14
14
|
import ChatPanelButton from './ChatPanel/ChatPanelButton';
|
|
@@ -28,6 +28,27 @@ const logo = {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalog/eventcatalog';
|
|
31
|
+
|
|
32
|
+
const user = session?.user as { name?: string; email?: string; image?: string; provider?: string } | undefined;
|
|
33
|
+
const userName = user?.name || user?.email || 'User';
|
|
34
|
+
const userInitials =
|
|
35
|
+
userName
|
|
36
|
+
.split(/[\s@.]+/)
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.map((part) => part[0])
|
|
39
|
+
.join('')
|
|
40
|
+
.substring(0, 2)
|
|
41
|
+
.toUpperCase() || 'U';
|
|
42
|
+
// Google avatar URLs are blocked by some browsers' tracking protection, so fall back to initials
|
|
43
|
+
const userImage = user?.image && !user.image.includes('googleusercontent.com') ? user.image : undefined;
|
|
44
|
+
const providerNames: Record<string, string> = {
|
|
45
|
+
github: 'GitHub',
|
|
46
|
+
google: 'Google',
|
|
47
|
+
okta: 'Okta',
|
|
48
|
+
auth0: 'Auth0',
|
|
49
|
+
'microsoft-entra-id': 'Microsoft Entra ID',
|
|
50
|
+
};
|
|
51
|
+
const providerName = user?.provider ? providerNames[user.provider] || user.provider : undefined;
|
|
31
52
|
---
|
|
32
53
|
|
|
33
54
|
<nav
|
|
@@ -58,46 +79,90 @@ const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalo
|
|
|
58
79
|
<button
|
|
59
80
|
id="profile-menu-button"
|
|
60
81
|
type="button"
|
|
61
|
-
class="flex items-center focus:outline-hidden focus:ring-2 focus
|
|
82
|
+
class="group flex items-center gap-1 rounded-full p-0.5 pr-1.5 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-icon-hover))] hover:bg-[rgb(var(--ec-dropdown-hover))] aria-expanded:bg-[rgb(var(--ec-dropdown-hover))] transition-colors focus:outline-hidden focus-visible:ring-2 focus-visible:ring-[rgb(var(--ec-accent))]"
|
|
62
83
|
aria-expanded="false"
|
|
63
|
-
aria-haspopup="
|
|
64
|
-
aria-
|
|
84
|
+
aria-haspopup="menu"
|
|
85
|
+
aria-controls="profile-dropdown"
|
|
86
|
+
aria-label={`Account menu for ${userName}`}
|
|
65
87
|
>
|
|
66
|
-
{
|
|
88
|
+
{userImage ? (
|
|
67
89
|
<img
|
|
68
|
-
src={
|
|
69
|
-
alt=
|
|
70
|
-
class="h-
|
|
90
|
+
src={userImage}
|
|
91
|
+
alt=""
|
|
92
|
+
class="h-8 w-8 rounded-full object-cover ring-1 ring-[rgb(var(--ec-page-border))]"
|
|
71
93
|
/>
|
|
72
94
|
) : (
|
|
73
|
-
<
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
.split(' ')
|
|
77
|
-
.map((n) => n[0])
|
|
78
|
-
.join('')
|
|
79
|
-
.substring(0, 2)
|
|
80
|
-
.toUpperCase()
|
|
81
|
-
: 'U'}
|
|
82
|
-
</div>
|
|
95
|
+
<span class="h-8 w-8 rounded-full bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))] ring-1 ring-[rgb(var(--ec-page-border))] flex items-center justify-center text-xs font-semibold">
|
|
96
|
+
{userInitials}
|
|
97
|
+
</span>
|
|
83
98
|
)}
|
|
99
|
+
<svg
|
|
100
|
+
viewBox="0 0 24 24"
|
|
101
|
+
class="h-4 w-4 transition-transform group-aria-expanded:rotate-180"
|
|
102
|
+
fill="none"
|
|
103
|
+
stroke="currentColor"
|
|
104
|
+
stroke-width="2"
|
|
105
|
+
stroke-linecap="round"
|
|
106
|
+
stroke-linejoin="round"
|
|
107
|
+
aria-hidden="true"
|
|
108
|
+
>
|
|
109
|
+
<path d="m6 9 6 6 6-6" />
|
|
110
|
+
</svg>
|
|
84
111
|
</button>
|
|
85
112
|
<div
|
|
86
113
|
id="profile-dropdown"
|
|
87
|
-
|
|
114
|
+
role="menu"
|
|
115
|
+
aria-labelledby="profile-menu-button"
|
|
116
|
+
class="ec-hidden absolute right-0 mt-2 w-64 bg-[rgb(var(--ec-dropdown-bg))] rounded-xl shadow-lg z-50 border border-[rgb(var(--ec-dropdown-border))] overflow-hidden"
|
|
88
117
|
>
|
|
89
|
-
<div class="
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
<div class="flex items-center gap-3 px-4 py-3 border-b border-[rgb(var(--ec-dropdown-border))]">
|
|
119
|
+
{userImage ? (
|
|
120
|
+
<img
|
|
121
|
+
src={userImage}
|
|
122
|
+
alt=""
|
|
123
|
+
class="h-10 w-10 shrink-0 rounded-full object-cover ring-1 ring-[rgb(var(--ec-page-border))]"
|
|
124
|
+
/>
|
|
125
|
+
) : (
|
|
126
|
+
<span class="h-10 w-10 shrink-0 rounded-full bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))] flex items-center justify-center text-sm font-semibold">
|
|
127
|
+
{userInitials}
|
|
128
|
+
</span>
|
|
93
129
|
)}
|
|
130
|
+
<div class="min-w-0">
|
|
131
|
+
<div class="truncate text-sm font-semibold text-[rgb(var(--ec-dropdown-text))]">{userName}</div>
|
|
132
|
+
{user?.email && user.email !== userName && (
|
|
133
|
+
<div class="truncate text-xs font-normal text-[rgb(var(--ec-page-text-muted))]">{user.email}</div>
|
|
134
|
+
)}
|
|
135
|
+
{providerName && (
|
|
136
|
+
<div class="truncate text-xs font-normal text-[rgb(var(--ec-page-text-muted))]">
|
|
137
|
+
Signed in with {providerName}
|
|
138
|
+
</div>
|
|
139
|
+
)}
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="p-1">
|
|
143
|
+
<button
|
|
144
|
+
id="signout-btn"
|
|
145
|
+
type="button"
|
|
146
|
+
role="menuitem"
|
|
147
|
+
class="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium text-[rgb(var(--ec-dropdown-text))] hover:bg-[rgb(var(--ec-dropdown-hover))] focus:outline-hidden focus-visible:bg-[rgb(var(--ec-dropdown-hover))] transition-colors"
|
|
148
|
+
>
|
|
149
|
+
<svg
|
|
150
|
+
viewBox="0 0 24 24"
|
|
151
|
+
class="h-4 w-4 text-[rgb(var(--ec-icon-color))]"
|
|
152
|
+
fill="none"
|
|
153
|
+
stroke="currentColor"
|
|
154
|
+
stroke-width="2"
|
|
155
|
+
stroke-linecap="round"
|
|
156
|
+
stroke-linejoin="round"
|
|
157
|
+
aria-hidden="true"
|
|
158
|
+
>
|
|
159
|
+
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
|
160
|
+
<polyline points="16 17 21 12 16 7" />
|
|
161
|
+
<line x1="21" x2="9" y1="12" y2="12" />
|
|
162
|
+
</svg>
|
|
163
|
+
Sign out
|
|
164
|
+
</button>
|
|
94
165
|
</div>
|
|
95
|
-
<button
|
|
96
|
-
id="signout-btn"
|
|
97
|
-
class="block w-full text-left px-4 py-2 text-sm text-[rgb(var(--ec-dropdown-text))] hover:bg-[rgb(var(--ec-dropdown-hover))] transition-colors font-medium"
|
|
98
|
-
>
|
|
99
|
-
Sign out
|
|
100
|
-
</button>
|
|
101
166
|
</div>
|
|
102
167
|
</div>
|
|
103
168
|
</div>
|
|
@@ -210,9 +275,15 @@ const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalo
|
|
|
210
275
|
<!-- Spacer to prevent content from being hidden under the fixed header -->
|
|
211
276
|
|
|
212
277
|
<script>
|
|
213
|
-
import { signOut } from 'auth-astro/client';
|
|
278
|
+
import { signOut } from '@utils/auth-astro/client';
|
|
214
279
|
|
|
215
280
|
function initializeHeader() {
|
|
281
|
+
// ClientRouter fires astro:page-load on the first load too, and the header persists across
|
|
282
|
+
// navigations. Bind once per element so clicks don't toggle the menus open and shut again.
|
|
283
|
+
const header = document.getElementById('eventcatalog-header');
|
|
284
|
+
if (!header || header.dataset.initialized === 'true') return;
|
|
285
|
+
header.dataset.initialized = 'true';
|
|
286
|
+
|
|
216
287
|
const menuToggle = document.getElementById('menu-toggle');
|
|
217
288
|
const mobileMenu = document.getElementById('mobile-menu');
|
|
218
289
|
|
|
@@ -261,10 +332,7 @@ const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalo
|
|
|
261
332
|
}
|
|
262
333
|
}
|
|
263
334
|
|
|
264
|
-
// Initialize on first load
|
|
265
335
|
initializeHeader();
|
|
266
|
-
|
|
267
|
-
// Re-initialize after Astro view transitions (needed because of transition:persist on header)
|
|
268
336
|
document.addEventListener('astro:page-load', initializeHeader);
|
|
269
337
|
</script>
|
|
270
338
|
|
|
@@ -5,7 +5,7 @@ const { title, logo } = config;
|
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { isAuthEnabled, isSSR } from '@utils/feature';
|
|
7
7
|
import { buildUrl } from '@utils/url-builder';
|
|
8
|
-
import { getSession } from 'auth-astro/server';
|
|
8
|
+
import { getSession } from '@utils/auth-astro/server';
|
|
9
9
|
|
|
10
10
|
const catalogDirectory = process.env.PROJECT_DIR || process.cwd();
|
|
11
11
|
|
|
@@ -408,7 +408,7 @@ const providerConfig = {
|
|
|
408
408
|
</html>
|
|
409
409
|
|
|
410
410
|
<script>
|
|
411
|
-
import { signIn } from 'auth-astro/client';
|
|
411
|
+
import { signIn } from '@utils/auth-astro/client';
|
|
412
412
|
|
|
413
413
|
// Add event listeners to all provider login buttons
|
|
414
414
|
const providerButtons = document.querySelectorAll('.provider-login-btn');
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
// src/middleware/auth.ts
|
|
7
7
|
import type { MiddlewareHandler } from 'astro';
|
|
8
|
-
import { getSession } from 'auth-astro/server';
|
|
8
|
+
import { getSession } from '@utils/auth-astro/server';
|
|
9
9
|
import { isAuthEnabled, isEventCatalogMCPAuthEnabled } from '@utils/feature';
|
|
10
10
|
import jwt from 'jsonwebtoken';
|
|
11
11
|
import { isLLMSTxtEnabled } from '@utils/feature';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from auth-astro 4.2.0 (MIT, https://github.com/nowaythatworked/auth-astro).
|
|
3
|
+
* See ./config.ts for why this lives in Core.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
interface AstroSignInOptions extends Record<string, unknown> {
|
|
7
|
+
/** Where to send the user after signing in. Defaults to the current page. */
|
|
8
|
+
callbackUrl?: string;
|
|
9
|
+
/** Redirect after signing in. Defaults to `true`. */
|
|
10
|
+
redirect?: boolean;
|
|
11
|
+
/** Base path for authentication. Defaults to `/api/auth`. */
|
|
12
|
+
prefix?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface AstroSignOutParams {
|
|
16
|
+
/** Where to send the user after signing out. Defaults to the current page. */
|
|
17
|
+
callbackUrl?: string;
|
|
18
|
+
/** Base path for authentication. Defaults to `/api/auth`. */
|
|
19
|
+
prefix?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Starts a sign-in flow for a provider. Adds the CSRF token to the request.
|
|
24
|
+
*/
|
|
25
|
+
export async function signIn(providerId?: string, options?: AstroSignInOptions, authorizationParams?: Record<string, string>) {
|
|
26
|
+
const { callbackUrl = window.location.href, redirect = true } = options ?? {};
|
|
27
|
+
const { prefix = '/api/auth', ...opts } = options ?? {};
|
|
28
|
+
|
|
29
|
+
const isCredentials = providerId === 'credentials';
|
|
30
|
+
const isEmail = providerId === 'email';
|
|
31
|
+
const isSupportingReturn = isCredentials || isEmail;
|
|
32
|
+
|
|
33
|
+
const signInUrl = `${prefix}/${isCredentials ? 'callback' : 'signin'}/${providerId}`;
|
|
34
|
+
const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`;
|
|
35
|
+
|
|
36
|
+
const csrfTokenResponse = await fetch(`${prefix}/csrf`);
|
|
37
|
+
const { csrfToken } = await csrfTokenResponse.json();
|
|
38
|
+
|
|
39
|
+
const res = await fetch(_signInUrl, {
|
|
40
|
+
method: 'post',
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
43
|
+
'X-Auth-Return-Redirect': '1',
|
|
44
|
+
},
|
|
45
|
+
body: new URLSearchParams({
|
|
46
|
+
...(opts as Record<string, string>),
|
|
47
|
+
csrfToken,
|
|
48
|
+
callbackUrl,
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const data = await res.clone().json();
|
|
53
|
+
const error = new URL(data.url).searchParams.get('error');
|
|
54
|
+
|
|
55
|
+
if (redirect || !isSupportingReturn || !error) {
|
|
56
|
+
window.location.href = data.url ?? callbackUrl;
|
|
57
|
+
// The browser does not reload when only the hash changes
|
|
58
|
+
if (data.url.includes('#')) window.location.reload();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return res;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Signs the user out by removing the session cookie. Adds the CSRF token to the request.
|
|
67
|
+
*/
|
|
68
|
+
export async function signOut(options?: AstroSignOutParams) {
|
|
69
|
+
const { callbackUrl = window.location.href, prefix = '/api/auth' } = options ?? {};
|
|
70
|
+
const csrfTokenResponse = await fetch(`${prefix}/csrf`);
|
|
71
|
+
const { csrfToken } = await csrfTokenResponse.json();
|
|
72
|
+
const res = await fetch(`${prefix}/signout`, {
|
|
73
|
+
method: 'post',
|
|
74
|
+
headers: {
|
|
75
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
76
|
+
'X-Auth-Return-Redirect': '1',
|
|
77
|
+
},
|
|
78
|
+
body: new URLSearchParams({
|
|
79
|
+
csrfToken,
|
|
80
|
+
callbackUrl,
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
const data = await res.json();
|
|
84
|
+
|
|
85
|
+
const url = data.url ?? callbackUrl;
|
|
86
|
+
window.location.href = url;
|
|
87
|
+
// The browser does not reload when only the hash changes
|
|
88
|
+
if (url.includes('#')) window.location.reload();
|
|
89
|
+
}
|