@burdenoff/microfe-eventfullymanaged 2026.828.1 → 2026.1030.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.
@@ -0,0 +1,133 @@
1
+ //#region src/utils/pageContext.ts
2
+ var e = "/eventfullymanaged", t = "([^/]+)", n = "(?!create(?:/|$))", r = [
3
+ {
4
+ pattern: RegExp(`^/events/${n}[^/]+/sessions/${n}${t}/edit$`),
5
+ entityType: "EVENTFULLYMANAGED_SESSION"
6
+ },
7
+ {
8
+ pattern: RegExp(`^/events/${n}[^/]+/tickets/${n}${t}/edit$`),
9
+ entityType: "EVENTFULLYMANAGED_TICKET_TYPE"
10
+ },
11
+ {
12
+ pattern: RegExp(`^/events/${n}${t}/sessions/create$`),
13
+ entityType: "EVENTFULLYMANAGED_EVENT",
14
+ activeTab: "sessions"
15
+ },
16
+ {
17
+ pattern: RegExp(`^/events/${n}${t}/tickets/create$`),
18
+ entityType: "EVENTFULLYMANAGED_EVENT",
19
+ activeTab: "tickets"
20
+ },
21
+ {
22
+ pattern: RegExp(`^/events/${n}${t}/virtual$`),
23
+ entityType: "EVENTFULLYMANAGED_EVENT",
24
+ activeTab: "virtual"
25
+ },
26
+ {
27
+ pattern: RegExp(`^/events/${n}${t}(?:/edit)?$`),
28
+ entityType: "EVENTFULLYMANAGED_EVENT"
29
+ },
30
+ {
31
+ pattern: RegExp(`^/venues/${n}${t}/floor-plans$`),
32
+ entityType: "EVENTFULLYMANAGED_VENUE",
33
+ activeTab: "floor-plans"
34
+ },
35
+ {
36
+ pattern: RegExp(`^/venues/${n}${t}/resources$`),
37
+ entityType: "EVENTFULLYMANAGED_VENUE",
38
+ activeTab: "resources"
39
+ },
40
+ {
41
+ pattern: RegExp(`^/venues/${n}${t}(?:/edit)?$`),
42
+ entityType: "EVENTFULLYMANAGED_VENUE"
43
+ },
44
+ {
45
+ pattern: RegExp(`^/sponsors/${n}${t}/leads$`),
46
+ entityType: "EVENTFULLYMANAGED_SPONSOR",
47
+ activeTab: "leads"
48
+ },
49
+ {
50
+ pattern: RegExp(`^/sponsors/${n}${t}(?:/edit)?$`),
51
+ entityType: "EVENTFULLYMANAGED_SPONSOR"
52
+ },
53
+ {
54
+ pattern: RegExp(`^/speakers/${n}${t}/edit$`),
55
+ entityType: "EVENTFULLYMANAGED_SPEAKER"
56
+ },
57
+ {
58
+ pattern: RegExp(`^/registration/attendees/${n}${t}/edit$`),
59
+ entityType: "EVENTFULLYMANAGED_ATTENDEE"
60
+ },
61
+ {
62
+ pattern: RegExp(`^/attendees/${t}/profile$`),
63
+ entityType: "EVENTFULLYMANAGED_ATTENDEE",
64
+ activeTab: "profile"
65
+ },
66
+ {
67
+ pattern: RegExp(`^/registration/promo-codes/${n}${t}/edit$`),
68
+ entityType: "EVENTFULLYMANAGED_PROMO_CODE"
69
+ },
70
+ {
71
+ pattern: RegExp(`^/networking/profiles/${n}${t}/edit$`),
72
+ entityType: "EVENTFULLYMANAGED_NETWORKING_PROFILE"
73
+ },
74
+ {
75
+ pattern: RegExp(`^/networking/meetings/${n}${t}/edit$`),
76
+ entityType: "EVENTFULLYMANAGED_MEETING"
77
+ },
78
+ {
79
+ pattern: RegExp(`^/exhibitors/${n}${t}/edit$`),
80
+ entityType: "EVENTFULLYMANAGED_EXHIBITOR"
81
+ }
82
+ ], i = /^[A-Za-z0-9_-]{1,128}$/;
83
+ function a(t) {
84
+ let n = t;
85
+ return (n === e || n.startsWith(`${e}/`)) && (n = n.slice(18)), n = n.replace(/\/+$/, ""), n === "" ? "/" : n;
86
+ }
87
+ function o(e) {
88
+ try {
89
+ return decodeURIComponent(e);
90
+ } catch {
91
+ return;
92
+ }
93
+ }
94
+ function s(e) {
95
+ let t = a(e);
96
+ for (let e of r) {
97
+ let n = e.pattern.exec(t);
98
+ if (!n?.[1]) continue;
99
+ let r = o(n[1]);
100
+ return !r || !i.test(r) ? {} : {
101
+ entityType: e.entityType,
102
+ entityId: r,
103
+ ...e.activeTab ? { activeTab: e.activeTab } : {}
104
+ };
105
+ }
106
+ return {};
107
+ }
108
+ function c(e) {
109
+ let t = a(e).split("/").filter(Boolean);
110
+ return t.length ? ["eventfullymanaged", ...t].slice(0, 3).join("/") : "eventfullymanaged";
111
+ }
112
+ function l() {
113
+ return "2026.1030.1";
114
+ }
115
+ function u() {
116
+ let { origin: e, pathname: t } = window.location, n = s(t);
117
+ return {
118
+ currentUrl: `${e}${t}`,
119
+ currentPage: c(t),
120
+ ...n.entityType ? {
121
+ entityType: n.entityType,
122
+ entityId: n.entityId
123
+ } : {},
124
+ ...n.activeTab ? { activeTab: n.activeTab } : {},
125
+ platform: "eventfullymanaged",
126
+ version: l(),
127
+ viewportSize: `${window.innerWidth}x${window.innerHeight}`
128
+ };
129
+ }
130
+ //#endregion
131
+ export { u as gatherPageContext };
132
+
133
+ //# sourceMappingURL=pageContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageContext.js","names":[],"sources":["../../src/utils/pageContext.ts"],"sourcesContent":["/**\n * Page context for the EventfullyManaged AI assistant (BOFF-3741).\n *\n * Captures where the organizer is in the app — the URL, the page and the record\n * on screen — so the floating assistant can act on \"this event\", \"this session\"\n * or \"here\" without asking which record the user means.\n *\n * Data boundary: this module emits ids and route names only. It never reads the\n * DOM, the Apollo cache or any form state, so attendee names and emails, lead\n * contact details, speaker bios and networking-profile free text cannot reach\n * the assistant through it. The query string and fragment are dropped from\n * `currentUrl` as well: they can carry search text or tokens, and the sandbox's\n * key allow-list only filters keys after the payload has left the browser.\n */\n\n/**\n * Entity types the assistant understands for EventfullyManaged. The api-calls\n * guide in algoshred/ai-assistant (`context/api-calls/products/eventfullymanaged.md`)\n * documents each one with the query that reads it; keep the two in step.\n */\nexport const EVENTFULLYMANAGED_ENTITY_TYPES = [\n 'EVENTFULLYMANAGED_EVENT',\n 'EVENTFULLYMANAGED_SESSION',\n 'EVENTFULLYMANAGED_TICKET_TYPE',\n 'EVENTFULLYMANAGED_VENUE',\n 'EVENTFULLYMANAGED_SPONSOR',\n 'EVENTFULLYMANAGED_SPEAKER',\n 'EVENTFULLYMANAGED_ATTENDEE',\n 'EVENTFULLYMANAGED_PROMO_CODE',\n 'EVENTFULLYMANAGED_NETWORKING_PROFILE',\n 'EVENTFULLYMANAGED_MEETING',\n 'EVENTFULLYMANAGED_EXHIBITOR',\n] as const;\n\nexport type EventfullyManagedEntityType = (typeof EVENTFULLYMANAGED_ENTITY_TYPES)[number];\n\n/**\n * A `type` alias rather than an `interface`, on purpose: TypeScript gives a type\n * alias an implicit index signature, which keeps it assignable to the shared\n * transport's `gatherPageContext: () => object` seam without a cast.\n *\n * Every key here is on the sandbox agent's allow-list\n * (`ALLOWED_CONTEXT_KEYS` in ai-assistant `src/context-loader.ts`). In particular\n * the URL key is `currentUrl`: an `activeUrl` key would be silently dropped.\n */\nexport type PageContext = {\n currentUrl: string;\n currentPage: string;\n entityType?: EventfullyManagedEntityType;\n entityId?: string;\n activeTab?: string;\n platform: string;\n version: string;\n viewportSize: string;\n};\n\nexport interface ResolvedEntity {\n entityType?: EventfullyManagedEntityType;\n entityId?: string;\n activeTab?: string;\n}\n\n/** The app shell mounts the MFE at this base path (`AppRoutes.tsx`). */\nconst BASE_PATH = '/eventfullymanaged';\n\n/**\n * Route → entity table, mirroring `EventfullyManagedRoutes.tsx`.\n *\n * Order matters: nested routes come before their parents so a session edit page\n * resolves to the session (the innermost record), not to its event. Create\n * pages under a parent (`events/:id/sessions/create`) deliberately fall through\n * to the parent row, because on those pages \"this event\" is the parent. A bare\n * `create` page is never treated as a record: `(?!create$)` stops\n * `/events/create` from becoming an event whose id is the word \"create\".\n *\n * `activeTab` names the sub-page when the route is a view of a record rather\n * than the record itself (a venue's floor plans, a sponsor's leads).\n */\nconst ID = '([^/]+)';\nconst NOT_CREATE = '(?!create(?:/|$))';\n\nconst ROUTES: ReadonlyArray<{\n pattern: RegExp;\n entityType: EventfullyManagedEntityType;\n activeTab?: string;\n}> = [\n {\n pattern: new RegExp(`^/events/${NOT_CREATE}[^/]+/sessions/${NOT_CREATE}${ID}/edit$`),\n entityType: 'EVENTFULLYMANAGED_SESSION',\n },\n {\n pattern: new RegExp(`^/events/${NOT_CREATE}[^/]+/tickets/${NOT_CREATE}${ID}/edit$`),\n entityType: 'EVENTFULLYMANAGED_TICKET_TYPE',\n },\n {\n pattern: new RegExp(`^/events/${NOT_CREATE}${ID}/sessions/create$`),\n entityType: 'EVENTFULLYMANAGED_EVENT',\n activeTab: 'sessions',\n },\n {\n pattern: new RegExp(`^/events/${NOT_CREATE}${ID}/tickets/create$`),\n entityType: 'EVENTFULLYMANAGED_EVENT',\n activeTab: 'tickets',\n },\n {\n pattern: new RegExp(`^/events/${NOT_CREATE}${ID}/virtual$`),\n entityType: 'EVENTFULLYMANAGED_EVENT',\n activeTab: 'virtual',\n },\n { pattern: new RegExp(`^/events/${NOT_CREATE}${ID}(?:/edit)?$`), entityType: 'EVENTFULLYMANAGED_EVENT' },\n {\n pattern: new RegExp(`^/venues/${NOT_CREATE}${ID}/floor-plans$`),\n entityType: 'EVENTFULLYMANAGED_VENUE',\n activeTab: 'floor-plans',\n },\n {\n pattern: new RegExp(`^/venues/${NOT_CREATE}${ID}/resources$`),\n entityType: 'EVENTFULLYMANAGED_VENUE',\n activeTab: 'resources',\n },\n { pattern: new RegExp(`^/venues/${NOT_CREATE}${ID}(?:/edit)?$`), entityType: 'EVENTFULLYMANAGED_VENUE' },\n {\n pattern: new RegExp(`^/sponsors/${NOT_CREATE}${ID}/leads$`),\n entityType: 'EVENTFULLYMANAGED_SPONSOR',\n activeTab: 'leads',\n },\n { pattern: new RegExp(`^/sponsors/${NOT_CREATE}${ID}(?:/edit)?$`), entityType: 'EVENTFULLYMANAGED_SPONSOR' },\n { pattern: new RegExp(`^/speakers/${NOT_CREATE}${ID}/edit$`), entityType: 'EVENTFULLYMANAGED_SPEAKER' },\n {\n pattern: new RegExp(`^/registration/attendees/${NOT_CREATE}${ID}/edit$`),\n entityType: 'EVENTFULLYMANAGED_ATTENDEE',\n },\n {\n pattern: new RegExp(`^/attendees/${ID}/profile$`),\n entityType: 'EVENTFULLYMANAGED_ATTENDEE',\n activeTab: 'profile',\n },\n {\n pattern: new RegExp(`^/registration/promo-codes/${NOT_CREATE}${ID}/edit$`),\n entityType: 'EVENTFULLYMANAGED_PROMO_CODE',\n },\n {\n pattern: new RegExp(`^/networking/profiles/${NOT_CREATE}${ID}/edit$`),\n entityType: 'EVENTFULLYMANAGED_NETWORKING_PROFILE',\n },\n {\n pattern: new RegExp(`^/networking/meetings/${NOT_CREATE}${ID}/edit$`),\n entityType: 'EVENTFULLYMANAGED_MEETING',\n },\n { pattern: new RegExp(`^/exhibitors/${NOT_CREATE}${ID}/edit$`), entityType: 'EVENTFULLYMANAGED_EXHIBITOR' },\n];\n\n/** Ids in this app are UUIDs or similar opaque tokens; anything else is not an id. */\nconst SAFE_ID = /^[A-Za-z0-9_-]{1,128}$/;\n\n/**\n * Strip the mount prefix and any trailing slash, so the table above matches\n * the same page whether the MFE runs inside the app shell\n * (`/eventfullymanaged/events/abc`) or standalone in dev (`/events/abc`).\n */\nexport function toProductPath(pathname: string): string {\n let path = pathname;\n if (path === BASE_PATH || path.startsWith(`${BASE_PATH}/`)) {\n path = path.slice(BASE_PATH.length);\n }\n path = path.replace(/\\/+$/, '');\n return path === '' ? '/' : path;\n}\n\nfunction decodeSegment(segment: string): string | undefined {\n try {\n return decodeURIComponent(segment);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the record the user is looking at from the route alone.\n *\n * Returns an empty object on list, dashboard and create pages: there is no\n * \"this\" there, and a guessed entity is worse than none because the assistant\n * would act on it confidently.\n */\nexport function resolveEventfullyManagedEntity(pathname: string): ResolvedEntity {\n const path = toProductPath(pathname);\n for (const route of ROUTES) {\n const match = route.pattern.exec(path);\n if (!match?.[1]) continue;\n const entityId = decodeSegment(match[1]);\n if (!entityId || !SAFE_ID.test(entityId)) return {};\n return {\n entityType: route.entityType,\n entityId,\n ...(route.activeTab ? { activeTab: route.activeTab } : {}),\n };\n }\n return {};\n}\n\n/**\n * Up to three path segments under the product, e.g. `events/<id>/sessions`.\n * Matches the shape every other product sends, so the agent can name the page.\n */\nexport function toCurrentPage(pathname: string): string {\n const segments = toProductPath(pathname).split('/').filter(Boolean);\n return segments.length ? ['eventfullymanaged', ...segments].slice(0, 3).join('/') : 'eventfullymanaged';\n}\n\n/**\n * The published MFE version, injected by `vite.config.ts` (`define`) from the\n * `MFE_VERSION` the Publish workflow computes. Undefined under Vitest and in a\n * local dev server, hence the `typeof` guard.\n */\ndeclare const __EVENTFULLYMANAGED_MFE_VERSION__: string | undefined;\n\nfunction appVersion(): string {\n const version = typeof __EVENTFULLYMANAGED_MFE_VERSION__ === 'string' ? __EVENTFULLYMANAGED_MFE_VERSION__ : undefined;\n return version && version.trim() ? version : 'dev';\n}\n\nexport function gatherPageContext(): PageContext {\n const { origin, pathname } = window.location;\n const entity = resolveEventfullyManagedEntity(pathname);\n return {\n currentUrl: `${origin}${pathname}`,\n currentPage: toCurrentPage(pathname),\n ...(entity.entityType ? { entityType: entity.entityType, entityId: entity.entityId } : {}),\n ...(entity.activeTab ? { activeTab: entity.activeTab } : {}),\n platform: 'eventfullymanaged',\n version: appVersion(),\n viewportSize: `${window.innerWidth}x${window.innerHeight}`,\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-eventfullymanaged",
3
- "version": "2026.828.1",
3
+ "version": "2026.1030.1",
4
4
  "description": "EventfullyManaged - End-to-end event management platform",
5
5
  "type": "module",
6
6
  "files": [