@eventcatalog/core 5.0.0-beta.27 → 5.0.0-beta.29

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.
Files changed (48) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +57 -3
  4. package/dist/analytics/log-build.d.cts +2 -2
  5. package/dist/analytics/log-build.d.ts +2 -2
  6. package/dist/analytics/log-build.js +5 -4
  7. package/dist/analytics/studio-usage.cjs +90 -0
  8. package/dist/analytics/studio-usage.d.cts +5 -0
  9. package/dist/analytics/studio-usage.d.ts +5 -0
  10. package/dist/analytics/studio-usage.js +10 -0
  11. package/dist/{chunk-ILPH363P.js → chunk-34VU2X7H.js} +1 -1
  12. package/dist/{chunk-I6CBMGUM.js → chunk-3RDV4HXA.js} +1 -1
  13. package/dist/{chunk-P5IFIKG6.js → chunk-4IREUUHE.js} +12 -4
  14. package/dist/{chunk-AWOO63ME.js → chunk-AD7CL772.js} +11 -4
  15. package/dist/{chunk-EFBDR7JJ.js → chunk-B4OOUG5I.js} +1 -1
  16. package/dist/chunk-CA6WCQ2T.js +54 -0
  17. package/dist/{chunk-QJ7KKN2D.js → chunk-OX6TSVHY.js} +1 -1
  18. package/dist/{chunk-YGUOLT7F.js → chunk-ZK7Q7XDV.js} +1 -1
  19. package/dist/constants.cjs +1 -1
  20. package/dist/constants.js +1 -1
  21. package/dist/eventcatalog.cjs +246 -186
  22. package/dist/eventcatalog.js +12 -10
  23. package/dist/federation/federate.js +3 -3
  24. package/dist/federation/source-provider.js +2 -2
  25. package/dist/generate.cjs +1 -1
  26. package/dist/generate.js +3 -3
  27. package/dist/utils/cli-logger.cjs +1 -1
  28. package/dist/utils/cli-logger.js +2 -2
  29. package/dist/utils/license-status.cjs +11 -4
  30. package/dist/utils/license-status.d.cts +3 -2
  31. package/dist/utils/license-status.d.ts +3 -2
  32. package/dist/utils/license-status.js +1 -1
  33. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +19 -2
  34. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +53 -48
  35. package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +183 -178
  36. package/eventcatalog/src/components/Settings/LicenseSettings.tsx +140 -31
  37. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +40 -35
  38. package/eventcatalog/src/components/Settings/LogoUpload.tsx +1 -1
  39. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +9 -8
  40. package/eventcatalog/src/components/Settings/Row.tsx +7 -4
  41. package/eventcatalog/src/components/Settings/SettingsShared.tsx +3 -3
  42. package/eventcatalog/src/components/TrialBadge.astro +20 -9
  43. package/eventcatalog/src/layouts/SettingsLayout.astro +2 -2
  44. package/eventcatalog/src/pages/settings/license.astro +9 -1
  45. package/eventcatalog/src/utils/license.ts +1 -1
  46. package/eventcatalog/src/utils/trial.ts +13 -0
  47. package/package.json +3 -3
  48. package/dist/{chunk-A2RZR3U4.js → chunk-6K7XZAYI.js} +3 -3
@@ -64,44 +64,49 @@ export const LlmAccessSettingsForm = ({ canEdit, initial, apiBase, llmsTxtUrl, l
64
64
  };
65
65
 
66
66
  return (
67
- <form onSubmit={(e) => e.preventDefault()} className="divide-y divide-[rgb(var(--ec-page-border))]">
67
+ <>
68
68
  <Toaster richColors closeButton position="bottom-right" theme="system" />
69
- {!canEdit && (
70
- <div className="pb-6">
71
- <ReadOnlyBanner />
72
- </div>
73
- )}
74
-
75
- <Row
76
- title="llms.txt"
77
- description="Generate llms.txt files so tools like Claude, ChatGPT, and Cursor can read your catalog at /llms.txt."
78
- canEdit={canEdit}
79
- dirty={dirty}
80
- saving={saving}
81
- onSave={save}
69
+ <form
70
+ onSubmit={(e) => e.preventDefault()}
71
+ className="divide-y divide-[rgb(var(--ec-page-border))] border-t border-[rgb(var(--ec-page-border))]"
82
72
  >
83
- <ToggleRow
84
- icon={<Bot className="h-4 w-4" aria-hidden />}
85
- label={llmsTxtEnabled ? 'Enabled' : 'Disabled'}
86
- hint={
87
- llmsTxtEnabled ? 'AI tools can read your catalog at /llms.txt.' : 'AI tools will not be able to read your catalog.'
88
- }
89
- checked={llmsTxtEnabled}
90
- disabled={!canEdit}
91
- onChange={setLlmsTxtEnabled}
92
- />
93
- {llmsTxtEnabled && <LlmsTxtPreview url={llmsTxtUrl} fullUrl={llmsFullTxtUrl} />}
94
- </Row>
73
+ {!canEdit && (
74
+ <div className="pb-6">
75
+ <ReadOnlyBanner />
76
+ </div>
77
+ )}
95
78
 
96
- <Row
97
- title="schemas.txt"
98
- description="Give LLMs access to every schema across your organization in one place — events, commands, queries, and services."
99
- canEdit={false}
100
- dirty={false}
101
- >
102
- <SchemasTxtAvailable url={schemasTxtUrl} />
103
- </Row>
104
- </form>
79
+ <Row
80
+ title="llms.txt"
81
+ description="Generate llms.txt files so tools like Claude, ChatGPT, and Cursor can read your catalog at /llms.txt."
82
+ canEdit={canEdit}
83
+ dirty={dirty}
84
+ saving={saving}
85
+ onSave={save}
86
+ >
87
+ <ToggleRow
88
+ icon={<Bot className="h-4 w-4" aria-hidden />}
89
+ label={llmsTxtEnabled ? 'Enabled' : 'Disabled'}
90
+ hint={
91
+ llmsTxtEnabled ? 'AI tools can read your catalog at /llms.txt.' : 'AI tools will not be able to read your catalog.'
92
+ }
93
+ checked={llmsTxtEnabled}
94
+ disabled={!canEdit}
95
+ onChange={setLlmsTxtEnabled}
96
+ />
97
+ {llmsTxtEnabled && <LlmsTxtPreview url={llmsTxtUrl} fullUrl={llmsFullTxtUrl} />}
98
+ </Row>
99
+
100
+ <Row
101
+ title="schemas.txt"
102
+ description="Give LLMs access to every schema across your organization in one place — events, commands, queries, and services."
103
+ canEdit={false}
104
+ dirty={false}
105
+ >
106
+ <SchemasTxtAvailable url={schemasTxtUrl} />
107
+ </Row>
108
+ </form>
109
+ </>
105
110
  );
106
111
  };
107
112
 
@@ -75,7 +75,7 @@ export const LogoUpload = ({ canEdit, initialSrc, apiUrl, onSrcChange }: LogoUpl
75
75
  onDrop={onDrop}
76
76
  className={`relative flex items-center gap-5 rounded-lg border border-dashed px-4 py-4 transition-colors ${
77
77
  dragOver
78
- ? 'border-[rgb(var(--ec-accent)/0.6)] bg-[rgb(var(--ec-accent-subtle)/0.4)]'
78
+ ? 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-text)/0.04)]'
79
79
  : 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg)/0.4)]'
80
80
  }`}
81
81
  >
@@ -26,7 +26,8 @@ interface Props {
26
26
 
27
27
  export const McpSettingsForm = ({ inSSR, mcpUrl, domainServers }: Props) => {
28
28
  return (
29
- <div className="divide-y divide-[rgb(var(--ec-page-border))]">
29
+ // A top border, as on the other settings pages
30
+ <div className="divide-y divide-[rgb(var(--ec-page-border))] border-t border-[rgb(var(--ec-page-border))]">
30
31
  <Row
31
32
  title="Catalog MCP Server"
32
33
  description="Connect AI agents (Claude, Cursor, VS Code and any MCP client) to every resource in your catalog: domains, services, messages, flows, schemas and the teams that own them."
@@ -63,7 +64,7 @@ const LivePill = () => (
63
64
  const CatalogServer = ({ url }: { url: string }) => (
64
65
  <div className="overflow-hidden rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))]">
65
66
  <div className="flex items-start gap-3 px-4 py-3.5">
66
- <span className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg border border-[rgb(var(--ec-accent)/0.3)] bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))]">
67
+ <span className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-text)/0.05)] text-[rgb(var(--ec-page-text))]">
67
68
  <Library className="h-4 w-4" aria-hidden />
68
69
  </span>
69
70
  <div className="min-w-0 flex-1">
@@ -83,7 +84,7 @@ const CatalogServer = ({ url }: { url: string }) => (
83
84
  href={MCP_DOCS_URL}
84
85
  target="_blank"
85
86
  rel="noreferrer"
86
- className="mt-3 inline-flex items-center gap-1 text-[12px] font-medium text-[rgb(var(--ec-accent))] hover:underline"
87
+ className="mt-3 inline-flex items-center gap-1 text-[12px] font-medium text-[rgb(var(--ec-page-text))] hover:underline"
87
88
  >
88
89
  How to connect a client
89
90
  <ArrowUpRight className="h-3.5 w-3.5" aria-hidden />
@@ -100,7 +101,7 @@ const DomainServers = ({ servers }: { servers: DomainMcpServer[] }) => (
100
101
  <a
101
102
  href={server.docsUrl}
102
103
  title={server.summary}
103
- className="inline-flex min-w-0 items-center gap-2 text-[13px] font-medium text-[rgb(var(--ec-page-text))] hover:text-[rgb(var(--ec-accent))]"
104
+ className="inline-flex min-w-0 items-center gap-2 text-[13px] font-medium text-[rgb(var(--ec-page-text))] hover:underline"
104
105
  >
105
106
  <Boxes className="h-3.5 w-3.5 flex-shrink-0 self-center text-[rgb(var(--ec-icon-color))]" aria-hidden />
106
107
  <span className="truncate">{server.name}</span>
@@ -114,15 +115,15 @@ const DomainServers = ({ servers }: { servers: DomainMcpServer[] }) => (
114
115
  );
115
116
 
116
117
  const McpNeedsSSR = () => (
117
- <div className="overflow-hidden rounded-lg border border-[rgb(var(--ec-accent)/0.4)] bg-gradient-to-br from-[rgb(var(--ec-accent)/0.1)] via-[rgb(var(--ec-accent)/0.05)] to-transparent">
118
+ <div className="overflow-hidden rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-text)/0.03)]">
118
119
  <div className="flex items-start gap-3 px-4 py-3.5">
119
- <span className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border border-[rgb(var(--ec-accent)/0.4)] bg-[rgb(var(--ec-accent)/0.1)] text-[rgb(var(--ec-accent))]">
120
+ <span className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-text)/0.05)] text-[rgb(var(--ec-page-text))]">
120
121
  <ServerCog className="h-4 w-4" aria-hidden />
121
122
  </span>
122
123
  <div className="flex-1 min-w-0">
123
124
  <div className="flex items-center gap-2">
124
125
  <p className="text-[13px] font-semibold text-[rgb(var(--ec-page-text))]">Server output mode required</p>
125
- <span className="inline-flex items-center gap-1 rounded-full border border-[rgb(var(--ec-accent)/0.4)] bg-[rgb(var(--ec-accent)/0.1)] px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-[rgb(var(--ec-accent))]">
126
+ <span className="inline-flex items-center gap-1 rounded-full border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-text)/0.05)] px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-[rgb(var(--ec-page-text))]">
126
127
  SSR
127
128
  </span>
128
129
  </div>
@@ -134,7 +135,7 @@ const McpNeedsSSR = () => (
134
135
  href={MCP_DOCS_URL}
135
136
  target="_blank"
136
137
  rel="noreferrer"
137
- className="inline-flex items-center gap-1 rounded-md bg-[rgb(var(--ec-accent))] px-3 py-1.5 text-[12px] font-semibold text-white shadow-sm transition-colors hover:bg-[rgb(var(--ec-accent-hover))]"
138
+ className="inline-flex items-center gap-1 rounded-md bg-[rgb(var(--ec-page-text))] px-3 py-1.5 text-[12px] font-semibold text-[rgb(var(--ec-page-bg))] shadow-sm transition-colors hover:opacity-85"
138
139
  >
139
140
  MCP setup guide
140
141
  <ExternalLink className="h-3 w-3" aria-hidden />
@@ -3,7 +3,7 @@ import { AlertCircle } from 'lucide-react';
3
3
  export const cn = (...parts: Array<string | false | undefined | null>): string => parts.filter(Boolean).join(' ');
4
4
 
5
5
  export const inputBase =
6
- 'block w-full rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-input-bg,var(--ec-page-bg)))] px-3 py-2 text-[13px] text-[rgb(var(--ec-page-text))] placeholder:text-[rgb(var(--ec-page-text-muted)/0.7)] transition-colors focus:border-[rgb(var(--ec-accent)/0.6)] focus:outline-none focus:ring-2 focus:ring-[rgb(var(--ec-accent)/0.25)] disabled:cursor-not-allowed disabled:opacity-60';
6
+ 'block w-full rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-input-bg,var(--ec-page-bg)))] px-3 py-2 text-[13px] text-[rgb(var(--ec-page-text))] placeholder:text-[rgb(var(--ec-page-text-muted)/0.7)] transition-colors focus:border-[rgb(var(--ec-page-text)/0.5)] focus:outline-none focus:ring-2 focus:ring-[rgb(var(--ec-page-text)/0.15)] disabled:cursor-not-allowed disabled:opacity-60';
7
7
 
8
8
  export const monoInput = 'font-mono text-[12.5px] tracking-tight';
9
9
 
@@ -11,7 +11,9 @@ export const inputError = 'border-red-500/70 focus:border-red-500 focus:ring-red
11
11
 
12
12
  interface RowProps {
13
13
  title: string;
14
- description: string;
14
+ description: React.ReactNode;
15
+ /** Shown under the description, in the left column */
16
+ aside?: React.ReactNode;
15
17
  canEdit: boolean;
16
18
  dirty: boolean;
17
19
  saving?: boolean;
@@ -20,13 +22,14 @@ interface RowProps {
20
22
  children: React.ReactNode;
21
23
  }
22
24
 
23
- export const Row = ({ title, description, canEdit, dirty, saving, onSave, error, children }: RowProps) => (
25
+ export const Row = ({ title, description, aside, canEdit, dirty, saving, onSave, error, children }: RowProps) => (
24
26
  <section className="grid grid-cols-1 gap-6 py-8 md:grid-cols-[minmax(0,_18rem)_minmax(0,_1fr)] md:gap-12">
25
27
  <header className="space-y-1.5">
26
28
  <h3 className="text-[14px] font-semibold tracking-tight text-[rgb(var(--ec-page-text))]">{title}</h3>
27
29
  <p className="text-[13px] leading-relaxed text-[rgb(var(--ec-content-text-muted,var(--ec-page-text-muted)))]">
28
30
  {description}
29
31
  </p>
32
+ {aside && <div className="pt-3">{aside}</div>}
30
33
  </header>
31
34
  <div className="space-y-2.5">
32
35
  {children}
@@ -45,7 +48,7 @@ export const Row = ({ title, description, canEdit, dirty, saving, onSave, error,
45
48
  className={cn(
46
49
  'inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-[12px] font-medium transition-colors',
47
50
  dirty && !saving
48
- ? 'border-[rgb(var(--ec-accent)/0.5)] bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent-text))] hover:bg-[rgb(var(--ec-accent-subtle)/0.8)]'
51
+ ? 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-text)/0.05)] text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-page-text)/0.08)]'
49
52
  : 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] text-[rgb(var(--ec-page-text-muted))]',
50
53
  'disabled:cursor-not-allowed disabled:opacity-60'
51
54
  )}
@@ -32,7 +32,7 @@ export const UrlPanel = ({ url }: UrlPanelProps) => {
32
32
  href={url}
33
33
  target="_blank"
34
34
  rel="noreferrer"
35
- className="flex-1 truncate rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] px-2.5 py-1.5 font-mono text-[12px] text-[rgb(var(--ec-page-text))] transition-colors hover:border-[rgb(var(--ec-accent)/0.5)] hover:text-[rgb(var(--ec-accent))]"
35
+ className="flex-1 truncate rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] px-2.5 py-1.5 font-mono text-[12px] text-[rgb(var(--ec-page-text))] transition-colors hover:border-[rgb(var(--ec-page-text)/0.4)]"
36
36
  >
37
37
  {fullUrl}
38
38
  </a>
@@ -72,13 +72,13 @@ export const Toggle = ({ checked, disabled, onChange }: ToggleProps) => (
72
72
  onClick={() => onChange(!checked)}
73
73
  className={cn(
74
74
  'relative inline-flex h-5 w-9 flex-shrink-0 cursor-pointer items-center rounded-full transition-colors',
75
- checked ? 'bg-[rgb(var(--ec-accent))]' : 'bg-[rgb(var(--ec-page-text-muted)/0.35)]',
75
+ checked ? 'bg-[rgb(var(--ec-page-text))]' : 'bg-[rgb(var(--ec-page-text-muted)/0.35)]',
76
76
  disabled && 'cursor-not-allowed opacity-50'
77
77
  )}
78
78
  >
79
79
  <span
80
80
  className={cn(
81
- 'inline-block h-3.5 w-3.5 transform rounded-full bg-white shadow-sm transition-transform',
81
+ 'inline-block h-3.5 w-3.5 transform rounded-full bg-[rgb(var(--ec-page-bg))] shadow-sm transition-transform',
82
82
  checked ? 'translate-x-[1.125rem]' : 'translate-x-[0.1875rem]'
83
83
  )}
84
84
  />
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import catalog from '@utils/eventcatalog-config/catalog';
3
3
  import { isDevMode } from '@utils/feature';
4
- import { getLicenseDaysLeft, getTrialStatus, LICENSE_FAQ_URL, TRIAL_LENGTH_DAYS } from '@utils/trial';
4
+ import { BUY_BUSINESS_URL, getLicenseDaysLeft, getTrialStatus, TRIAL_LENGTH_DAYS } from '@utils/trial';
5
5
  import { getLicenseStatus } from '@utils/license';
6
6
  import { buildUrl } from '@utils/url-builder';
7
7
 
@@ -29,20 +29,17 @@ const title = licenseExpired
29
29
  : licenseDaysLeft !== undefined
30
30
  ? `Your EventCatalog commercial license expires on ${licensedUntil?.toLocaleDateString()}. Renew it to keep using EventCatalog commercially.`
31
31
  : trial?.ended
32
- ? `Your ${TRIAL_LENGTH_DAYS}-day EventCatalog trial ended on ${trial.endsAt.toLocaleDateString()}. Learn about licensing.`
33
- : `You're on a ${TRIAL_LENGTH_DAYS}-day EventCatalog trial, ending on ${trial?.endsAt.toLocaleDateString()}. Learn about licensing.`;
32
+ ? `Your ${TRIAL_LENGTH_DAYS}-day EventCatalog trial ended on ${trial.endsAt.toLocaleDateString()}. See your license settings.`
33
+ : `You're on a ${TRIAL_LENGTH_DAYS}-day EventCatalog trial, ending on ${trial?.endsAt.toLocaleDateString()}. See your license settings.`;
34
34
  const warning = licenseExpired || licenseDaysLeft !== undefined || trial?.ended;
35
- // An expiring or expired license opens the license settings (where it's renewed), the trial the license FAQ
36
- const isLicense = licenseExpired || licenseDaysLeft !== undefined;
37
- const href = isLicense ? buildUrl('/settings/license') : LICENSE_FAQ_URL;
35
+ // The badge opens Settings > License, where the license is renewed or bought
36
+ const href = buildUrl('/settings/license');
38
37
  ---
39
38
 
40
39
  {
41
40
  (licenseExpired || licenseDaysLeft !== undefined || trial) && (
42
41
  <a
43
42
  href={href}
44
- target={isLicense ? undefined : '_blank'}
45
- rel={isLicense ? undefined : 'noopener noreferrer'}
46
43
  title={title}
47
44
  data-trial-ended={trial?.ended ? 'true' : undefined}
48
45
  data-license-expired={licenseExpired ? 'true' : undefined}
@@ -50,7 +47,7 @@ const href = isLicense ? buildUrl('/settings/license') : LICENSE_FAQ_URL;
50
47
  'inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-xs font-medium transition-colors',
51
48
  warning
52
49
  ? 'border-[rgb(var(--ec-badge-color-amber-text)/0.3)] bg-[rgb(var(--ec-badge-color-amber-background))] text-[rgb(var(--ec-badge-color-amber-text))] hover:opacity-90'
53
- : 'border-[rgb(var(--ec-accent)/0.3)] bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))] hover:bg-[rgb(var(--ec-accent)/0.15)]',
50
+ : 'border-transparent bg-[rgb(var(--ec-page-text))] text-[rgb(var(--ec-page-bg))] hover:opacity-85',
54
51
  ]}
55
52
  >
56
53
  <svg
@@ -80,3 +77,17 @@ const href = isLicense ? buildUrl('/settings/license') : LICENSE_FAQ_URL;
80
77
  </a>
81
78
  )
82
79
  }
80
+ {
81
+ /* Once the trial has ended, a link to buy the Business plan sits next to the badge */
82
+ trial?.ended && (
83
+ <a
84
+ href={BUY_BUSINESS_URL}
85
+ target="_blank"
86
+ rel="noopener noreferrer"
87
+ data-buy-business="true"
88
+ class="inline-flex items-center whitespace-nowrap rounded-full border border-transparent bg-[rgb(var(--ec-page-text))] px-2.5 py-1 text-xs font-medium text-[rgb(var(--ec-page-bg))] transition-opacity hover:opacity-85"
89
+ >
90
+ Buy Business
91
+ </a>
92
+ )
93
+ }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import VerticalSideBarLayout from './VerticalSideBarLayout.astro';
3
3
  import { buildUrl } from '@utils/url-builder';
4
- import { Settings, Server, Bot, FileText, BadgeCheck } from 'lucide-react';
4
+ import { Settings, Server, Bot, ScanText, BadgeCheck } from 'lucide-react';
5
5
 
6
6
  export type SettingsSection = 'general' | 'mcp' | 'assistant' | 'llm-access' | 'license';
7
7
 
@@ -55,7 +55,7 @@ const groups: SectionGroup[] = [
55
55
  id: 'llm-access',
56
56
  label: 'LLM Access',
57
57
  href: buildUrl('/settings/llm-access'),
58
- icon: FileText,
58
+ icon: ScanText,
59
59
  },
60
60
  ],
61
61
  },
@@ -11,8 +11,16 @@ const license: LicenseProps =
11
11
  ? { ...status, issuedAt: status.issuedAt?.getTime(), expiresAt: status.expiresAt?.getTime() }
12
12
  : status;
13
13
  const trialStartedAt = typeof catalog?.tsd === 'number' ? catalog.tsd : undefined;
14
+ // The license on the main branch, the same text as www.eventcatalog.dev/license
15
+ const licenseUrl = 'https://github.com/event-catalog/eventcatalog/blob/main/LICENSE';
14
16
  ---
15
17
 
16
18
  <SettingsLayout title="License" active="license">
17
- <LicenseSettings client:load license={license} trialStartedAt={trialStartedAt} renderedAt={Date.now()} />
19
+ <LicenseSettings
20
+ client:load
21
+ license={license}
22
+ trialStartedAt={trialStartedAt}
23
+ renderedAt={Date.now()}
24
+ licenseUrl={licenseUrl}
25
+ />
18
26
  </SettingsLayout>
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { clearCache, hasCommercialLicense, verifyOfflineLicense } from '@eventcatalog/license';
4
4
 
5
- export { LICENSE_FAQ_URL, LICENSE_RENEW_URL } from './trial';
5
+ export { BUY_BUSINESS_URL, LICENSE_FAQ_URL, LICENSE_RENEW_URL, PRICING_URL } from './trial';
6
6
 
7
7
  // Details from the license token
8
8
  export type LicenseDetails = { org?: string; licenseId?: string; issuedAt?: Date };
@@ -5,6 +5,19 @@ export const LICENSE_FAQ_URL = 'https://www.eventcatalog.dev/license-faq';
5
5
  // Where a commercial license is renewed
6
6
  export const LICENSE_RENEW_URL = 'https://eventcatalog.cloud';
7
7
 
8
+ // Where the Business plan is bought: the order form on the website
9
+ export const BUY_BUSINESS_URL = 'https://www.eventcatalog.dev/buy?source=cli';
10
+
11
+ // Prices for a commercial license, linked while the trial is running
12
+ export const PRICING_URL = 'https://www.eventcatalog.dev/pricing';
13
+
14
+ // Questions about licensing or buying: talk to the EventCatalog team
15
+ export const TALK_TO_US_URL = 'https://www.eventcatalog.dev/book-demo';
16
+
17
+ // Shown with the trial, so organisations that qualify for Free Use don't read it as "EventCatalog is now paid"
18
+ export const FREE_USE_NOTE =
19
+ 'Under $10M revenue and $10M raised, an individual or an open-source project? You qualify for Free Use; get a free key at eventcatalog.cloud.';
20
+
8
21
  const DAY_IN_MS = 24 * 60 * 60 * 1000;
9
22
 
10
23
  export type TrialStatus = {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "BUSL-1.1",
9
9
  "type": "module",
10
- "version": "5.0.0-beta.27",
10
+ "version": "5.0.0-beta.29",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -142,8 +142,8 @@
142
142
  "yjs": "^13.6.33",
143
143
  "zod": "^4.3.6",
144
144
  "@eventcatalog/linter": "1.2.0-beta.4",
145
- "@eventcatalog/sdk": "2.30.0-beta.1",
146
- "@eventcatalog/visualiser": "^5.0.0-beta.6"
145
+ "@eventcatalog/visualiser": "^5.0.0-beta.6",
146
+ "@eventcatalog/sdk": "2.30.0-beta.1"
147
147
  },
148
148
  "devDependencies": {
149
149
  "@astrojs/check": "^0.9.10",
@@ -1,9 +1,9 @@
1
- import {
2
- createFileSystemSourceProvider
3
- } from "./chunk-SDZQJTJW.js";
4
1
  import {
5
2
  createGitHubSourceProvider
6
3
  } from "./chunk-352FGP6W.js";
4
+ import {
5
+ createFileSystemSourceProvider
6
+ } from "./chunk-SDZQJTJW.js";
7
7
 
8
8
  // src/federation/source-provider.ts
9
9
  var createFederationSourceProvider = (projectDirectory, providers = {}) => {