@theseam/ui-common 1.0.2-beta.54 → 1.0.2-beta.58

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.
@@ -1 +1 @@
1
- {"version":3,"file":"theseam-ui-common-ai.mjs","sources":["../../../projects/ui-common/ai/public-api.ts","../../../projects/ui-common/ai/theseam-ui-common-ai.ts"],"sourcesContent":["export default {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAA,gBAAe,EAAE;;ACAjB;;AAEG"}
1
+ {"version":3,"file":"theseam-ui-common-ai.mjs","sources":["../../../projects/ui-common/ai/providers/lm-studio.ai-provider.ts","../../../projects/ui-common/ai/providers/openrouter.ai-provider.ts","../../../projects/ui-common/ai/providers/mock.ai-provider.ts","../../../projects/ui-common/ai/chat/chat-provider.ts","../../../projects/ui-common/ai/chat/chat-response-parser.ts","../../../projects/ui-common/ai/chat/chat-block-registry.ts","../../../projects/ui-common/ai/chat/chat-message.component.ts","../../../projects/ui-common/ai/chat/chat-input.component.ts","../../../projects/ui-common/ai/chat/chat.component.ts","../../../projects/ui-common/ai/chat/chat.component.html","../../../projects/ui-common/ai/chat/testing/chat.harness.ts","../../../projects/ui-common/ai/datatable-prompter/datatable-prompter-prompt-provider.ts","../../../projects/ui-common/ai/datatable-prompter/datatable-prompter.component.ts","../../../projects/ui-common/ai/datatable-prompter/datatable-prompter.component.html","../../../projects/ui-common/ai/theseam-ui-common-ai.ts"],"sourcesContent":["import { AiProvider, ChatMessage, ChatResponse } from './ai-provider'\n\nexport class LmStudioAiProvider implements AiProvider {\n async chat(messages: ChatMessage[]): Promise<ChatResponse> {\n const url = 'http://localhost:1234/v1/chat/completions'\n const headers = {\n 'Content-Type': 'application/json',\n }\n const model = 'model-identifier'\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n }),\n })\n\n const data = await response.json()\n console.log('Response from AI:', data)\n\n const content = data.choices[0].message.content\n console.log(`%cResponse from AI. content:\\n${content}`, 'color: limegreen;')\n\n return { content }\n }\n}\n","import { AiProvider, ChatMessage, ChatResponse } from './ai-provider'\n\nexport class OpenRouterAiProvider implements AiProvider {\n async chat(messages: ChatMessage[]): Promise<ChatResponse> {\n const defaultApiKey =\n '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'\n\n const url = 'https://openrouter.ai/api/v1/chat/completions'\n const apiKey = localStorage.getItem('openrouter-api-key') || defaultApiKey\n const headers = {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n }\n const model = 'google/gemini-2.5-flash'\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n response_format: { type: 'json_object' },\n }),\n })\n\n const data = await response.json()\n console.log('Response from AI:', data)\n\n const content = data.choices[0].message.content\n console.log(`%cResponse from AI. content:\\n${content}`, 'color: limegreen;')\n\n return { content }\n }\n}\n","import { AiProvider, ChatMessage, ChatResponse } from './ai-provider'\n\ntype MockResponse = string | ((messages: ChatMessage[]) => string)\n\nexport class MockAiProvider implements AiProvider {\n constructor(private readonly _response: MockResponse = 'Mock response') {}\n\n async chat(messages: ChatMessage[]): Promise<ChatResponse> {\n const content =\n typeof this._response === 'function'\n ? this._response(messages)\n : this._response\n return { content }\n }\n}\n","import { InjectionToken } from '@angular/core'\nimport { AiProvider } from '../providers/ai-provider'\n\nexport const THESEAM_CHAT_PROVIDER = new InjectionToken<AiProvider>(\n 'TheSeamChatProvider',\n)\n","export type ChatContentSegment =\n | { type: 'markdown'; content: string }\n | { type: 'custom-block'; tag: string; content: string }\n\n/**\n * Splits a raw AI response string into an ordered array of segments.\n * Fenced code blocks with `seam-` prefixed language tags become custom-block\n * segments; everything else stays as markdown.\n */\nexport function parseChatResponse(input: string): ChatContentSegment[] {\n if (!input) {\n return []\n }\n\n const segments: ChatContentSegment[] = []\n const pattern = /^```(seam-[\\w-]+)\\n([\\s\\S]*?)^```/gm\n\n let lastIndex = 0\n let match: RegExpExecArray | null\n\n while ((match = pattern.exec(input)) !== null) {\n if (match.index > lastIndex) {\n segments.push({\n type: 'markdown',\n content: input.slice(lastIndex, match.index),\n })\n }\n\n segments.push({\n type: 'custom-block',\n tag: match[1],\n content: match[2].replace(/\\n$/, ''),\n })\n\n lastIndex = match.index + match[0].length\n }\n\n if (lastIndex < input.length) {\n segments.push({ type: 'markdown', content: input.slice(lastIndex) })\n }\n\n return segments\n}\n","import { InjectionToken, Type } from '@angular/core'\n\nexport type ChatBlockRegistry = Map<string, Type<unknown>>\n\nexport const THESEAM_CHAT_BLOCK_REGISTRY =\n new InjectionToken<ChatBlockRegistry>('TheSeamChatBlockRegistry')\n","import {\n ChangeDetectionStrategy,\n Component,\n inject,\n Input,\n Injector,\n} from '@angular/core'\nimport { NgComponentOutlet, NgForOf, NgIf } from '@angular/common'\nimport { MarkdownComponent } from 'ngx-markdown'\n\nimport { ChatContentSegment } from './chat-response-parser'\nimport {\n ChatBlockRegistry,\n THESEAM_CHAT_BLOCK_REGISTRY,\n} from './chat-block-registry'\n\nexport interface ChatMessageDisplayModel {\n role: 'user' | 'assistant'\n segments: ChatContentSegment[]\n timestamp: Date\n}\n\n@Component({\n selector: 'seam-chat-message',\n imports: [NgForOf, NgIf, MarkdownComponent, NgComponentOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"seam-chat-message\"\n [class.seam-chat-message--user]=\"message.role === 'user'\"\n [class.seam-chat-message--assistant]=\"message.role === 'assistant'\"\n >\n <div class=\"seam-chat-message__role\">\n {{ message.role === 'user' ? 'You' : 'Assistant' }}\n </div>\n <div class=\"seam-chat-message__content\">\n <ng-container *ngFor=\"let segment of message.segments\">\n <markdown\n *ngIf=\"segment.type === 'markdown'\"\n [data]=\"segment.content\"\n ></markdown>\n <ng-container *ngIf=\"segment.type === 'custom-block'\">\n <ng-container\n *ngIf=\"\n _getBlockComponent(segment.tag) as blockComponent;\n else fallbackBlock\n \"\n >\n <ng-container\n *ngComponentOutlet=\"\n blockComponent;\n injector: _createBlockInjector(segment.content)\n \"\n ></ng-container>\n </ng-container>\n <ng-template #fallbackBlock>\n <markdown\n [data]=\"_buildFallbackMarkdown(segment.tag, segment.content)\"\n ></markdown>\n </ng-template>\n </ng-container>\n </ng-container>\n </div>\n </div>\n `,\n styles: [\n `\n .seam-chat-message {\n display: flex;\n flex-direction: column;\n padding: 8px 12px;\n margin-bottom: 8px;\n }\n\n .seam-chat-message--user {\n align-items: flex-end;\n }\n\n .seam-chat-message--user .seam-chat-message__content {\n background-color: #e8f5e9;\n border-radius: 8px;\n padding: 8px 12px;\n max-width: 80%;\n }\n\n .seam-chat-message--assistant .seam-chat-message__content {\n background-color: #f1f3f5;\n border-radius: 8px;\n padding: 8px 12px;\n max-width: 80%;\n }\n\n .seam-chat-message__role {\n font-size: 0.75rem;\n color: #6c757d;\n margin-bottom: 4px;\n }\n `,\n ],\n})\nexport class SeamChatMessageComponent {\n @Input({ required: true }) message!: ChatMessageDisplayModel\n\n private readonly _blockRegistry = inject(THESEAM_CHAT_BLOCK_REGISTRY, {\n optional: true,\n })\n private readonly _injector = inject(Injector)\n\n _getBlockComponent(tag: string) {\n return this._blockRegistry?.get(tag) ?? null\n }\n\n _createBlockInjector(content: string): Injector {\n return Injector.create({\n providers: [{ provide: 'CHAT_BLOCK_CONTENT', useValue: content }],\n parent: this._injector,\n })\n }\n\n _buildFallbackMarkdown(tag: string, content: string): string {\n return '```' + tag + '\\n' + content + '\\n```'\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n} from '@angular/core'\nimport { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'\n\nimport { TheSeamRichTextModule } from '@theseam/ui-common/rich-text'\nimport { TheSeamFormFieldModule } from '@theseam/ui-common/form-field'\nimport { TheSeamButtonsModule } from '@theseam/ui-common/buttons'\n\n@Component({\n selector: 'seam-chat-input',\n imports: [\n ReactiveFormsModule,\n TheSeamRichTextModule,\n TheSeamFormFieldModule,\n TheSeamButtonsModule,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"seam-chat-input\">\n <seam-form-field>\n <seam-rich-text\n [formControl]=\"_control\"\n [placeholder]=\"placeholder\"\n [disableRichText]=\"true\"\n [rows]=\"2.7\"\n [resizable]=\"false\"\n (keydown.enter)=\"_onEnterKey($event)\"\n ></seam-rich-text>\n </seam-form-field>\n <button\n seamButton\n theme=\"primary\"\n class=\"seam-chat-send-btn\"\n [disabled]=\"disabled || _control.invalid\"\n (click)=\"_onSend()\"\n >\n Send\n </button>\n </div>\n `,\n styles: [\n `\n .seam-chat-input {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n padding: 8px;\n border-top: 1px solid #dee2e6;\n }\n\n seam-form-field {\n flex: 1;\n }\n\n .seam-chat-send-btn {\n flex-shrink: 0;\n }\n `,\n ],\n})\nexport class SeamChatInputComponent {\n @Input() placeholder = 'Type a message...'\n @Input() disabled = false\n\n @Output() messageSent = new EventEmitter<string>()\n\n readonly _control = new FormControl<string>('', [Validators.required])\n\n _onEnterKey(event: Event) {\n const keyEvent = event as KeyboardEvent\n if (keyEvent.shiftKey) {\n return\n }\n keyEvent.preventDefault()\n this._onSend()\n }\n\n _onSend() {\n const value = this._control.value?.trim()\n if (!value || this.disabled) {\n return\n }\n this.messageSent.emit(value)\n this._control.reset()\n }\n}\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n inject,\n Input,\n NgZone,\n ViewChild,\n} from '@angular/core'\nimport { AsyncPipe, NgForOf, NgIf } from '@angular/common'\nimport { BehaviorSubject } from 'rxjs'\n\nimport { TheSeamOverlayScrollbarDirective } from '@theseam/ui-common/scrollbar'\n\nimport { ChatMessage } from '../providers/ai-provider'\nimport { THESEAM_CHAT_PROVIDER } from './chat-provider'\nimport { parseChatResponse } from './chat-response-parser'\nimport {\n ChatMessageDisplayModel,\n SeamChatMessageComponent,\n} from './chat-message.component'\nimport { SeamChatInputComponent } from './chat-input.component'\n\n@Component({\n selector: 'seam-chat',\n imports: [\n AsyncPipe,\n NgForOf,\n NgIf,\n SeamChatMessageComponent,\n SeamChatInputComponent,\n TheSeamOverlayScrollbarDirective,\n ],\n templateUrl: './chat.component.html',\n styleUrls: ['./chat.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamChatComponent implements AfterViewInit {\n private readonly _provider = inject(THESEAM_CHAT_PROVIDER, { optional: true })\n private readonly _cdr = inject(ChangeDetectorRef)\n private readonly _ngZone = inject(NgZone)\n\n @Input() systemPrompt = ''\n @Input() placeholder = 'Type a message...'\n\n @ViewChild('messageList') private _messageList?: ElementRef<HTMLElement>\n @ViewChild(TheSeamOverlayScrollbarDirective)\n private _messageListScrollbar?: TheSeamOverlayScrollbarDirective\n\n readonly _loadingSubject = new BehaviorSubject<boolean>(false)\n\n private _messages: ChatMessage[] = []\n _displayMessages: ChatMessageDisplayModel[] = []\n\n // Pixels of slack allowed when deciding if the viewport is \"at the bottom\".\n // Small enough that scrolling up a line unpins, but forgiving of sub-pixel drift.\n private readonly _pinnedThreshold = 32\n\n // True when the viewport is (or should be) tracking the latest content. Starts\n // true so the first messages scroll into view. Updated on every scroll event.\n private _isPinnedToBottom = true\n\n // Set when a user action (e.g. sending a message) requires the view to jump\n // to the bottom on the next content-size change, regardless of pinned state.\n // Cleared as soon as it's consumed.\n private _forceScrollOnNextResize = false\n\n ngAfterViewInit() {\n const scrollInstance = this._messageListScrollbar?.instance\n if (!scrollInstance) {\n return\n }\n // OverlayScrollbars callbacks run outside Angular already (the directive's\n // service initializes with runOutsideAngular). These handlers only update\n // local flags and call scroll() — no change detection needed.\n this._ngZone.runOutsideAngular(() => {\n scrollInstance.options({\n callbacks: {\n onScroll: () => this._updatePinnedState(),\n // Fires when the content's scrollable size changes: a new message\n // appended, a custom block finishing its async render, an image\n // finishing loading, etc. This removes the need for a setTimeout\n // hack because we react to actual size changes rather than guessing\n // when rendering has settled.\n onContentSizeChanged: () => this._maybeScrollToBottom(),\n },\n })\n })\n }\n\n async _onMessageSent(text: string) {\n if (this._loadingSubject.value || !this._provider) {\n if (!this._provider) {\n console.error('No chat provider configured.')\n }\n return\n }\n\n const userMessage: ChatMessage = { role: 'user', content: text }\n this._messages.push(userMessage)\n this._displayMessages = [\n ...this._displayMessages,\n {\n role: 'user',\n segments: [{ type: 'markdown', content: text }],\n timestamp: new Date(),\n },\n ]\n // The user just sent a message — jump to the bottom even if they had\n // scrolled up previously. Consumed by the next onContentSizeChanged.\n this._forceScrollOnNextResize = true\n this._cdr.markForCheck()\n\n this._loadingSubject.next(true)\n try {\n const messagesToSend: ChatMessage[] = []\n if (this.systemPrompt) {\n messagesToSend.push({ role: 'system', content: this.systemPrompt })\n }\n messagesToSend.push(...this._messages)\n\n const response = await this._provider.chat(messagesToSend)\n\n const assistantMessage: ChatMessage = {\n role: 'assistant',\n content: response.content,\n }\n this._messages.push(assistantMessage)\n this._displayMessages = [\n ...this._displayMessages,\n {\n role: 'assistant',\n segments: parseChatResponse(response.content),\n timestamp: new Date(),\n },\n ]\n } catch (err) {\n console.error('Chat provider error:', err)\n } finally {\n this._loadingSubject.next(false)\n this._cdr.markForCheck()\n }\n }\n\n private _updatePinnedState() {\n const scrollInstance = this._messageListScrollbar?.instance\n if (!scrollInstance) {\n return\n }\n const info = scrollInstance.scroll()\n this._isPinnedToBottom =\n info.position.y >= info.max.y - this._pinnedThreshold\n }\n\n private _maybeScrollToBottom() {\n // Auto-scroll only when the user expects it:\n // - They just sent a message (forceScroll), OR\n // - They were already following the latest content (pinnedToBottom).\n // If they scrolled up to read an earlier message, we leave their viewport\n // alone so continued content growth (e.g. a streaming answer or an\n // async-rendered block) doesn't keep yanking it back.\n if (this._forceScrollOnNextResize || this._isPinnedToBottom) {\n this._scrollToBottom()\n this._forceScrollOnNextResize = false\n }\n }\n\n private _scrollToBottom() {\n const scrollInstance = this._messageListScrollbar?.instance\n if (scrollInstance) {\n const state = scrollInstance.getState()\n scrollInstance.scroll({ y: state.contentScrollSize.height })\n }\n }\n}\n","<div class=\"seam-chat\">\n <div class=\"seam-chat__messages\" #messageList seamOverlayScrollbar>\n <seam-chat-message\n *ngFor=\"let msg of _displayMessages\"\n [message]=\"msg\"\n ></seam-chat-message>\n\n <div *ngIf=\"_loadingSubject | async\" class=\"seam-chat__loading\">\n <span>Thinking...</span>\n </div>\n </div>\n\n <seam-chat-input\n [placeholder]=\"placeholder\"\n [disabled]=\"!!(_loadingSubject | async)\"\n (messageSent)=\"_onMessageSent($event)\"\n ></seam-chat-input>\n</div>\n","import { ComponentHarness } from '@angular/cdk/testing'\n\nexport class TheSeamChatMessageHarness extends ComponentHarness {\n static hostSelector = 'seam-chat-message'\n\n private readonly _role = this.locatorForOptional('.seam-chat-message__role')\n private readonly _content = this.locatorForOptional(\n '.seam-chat-message__content',\n )\n\n async getRole(): Promise<string> {\n const roleEl = await this._role()\n const text = await roleEl?.text()\n return text?.trim().toLowerCase() ?? ''\n }\n\n async getText(): Promise<string> {\n const contentEl = await this._content()\n return (await contentEl?.text())?.trim() ?? ''\n }\n}\n\nexport class TheSeamChatInputHarness extends ComponentHarness {\n static hostSelector = 'seam-chat-input'\n\n async getSendButton() {\n return this.locatorFor('button')()\n }\n\n async isSendDisabled(): Promise<boolean> {\n const btn = await this.getSendButton()\n return (await btn.getAttribute('disabled')) !== null\n }\n}\n\nexport class TheSeamChatHarness extends ComponentHarness {\n static hostSelector = 'seam-chat'\n\n private readonly _messages = this.locatorForAll(TheSeamChatMessageHarness)\n private readonly _input = this.locatorFor(TheSeamChatInputHarness)\n private readonly _loading = this.locatorForOptional('.seam-chat__loading')\n\n async getMessages(): Promise<TheSeamChatMessageHarness[]> {\n return this._messages()\n }\n\n async getInput(): Promise<TheSeamChatInputHarness> {\n return this._input()\n }\n\n async isLoading(): Promise<boolean> {\n return (await this._loading()) !== null\n }\n}\n","import { InjectionToken } from '@angular/core'\n\nimport { AiProvider } from '../providers/ai-provider'\n\nexport const assistantPrompt = `You are a helpful assistant that provides formatting json code for a datatable.\nA datatable is a table that displays data in rows and columns, similar to a spreadsheet, with column sorting and data filtering.\n\nYour job is not to provide a descriptive analysis of the request or any additional information. The user will ignore anything that is not a JSON object.\n\nThe user will provide a request, and you will respond with a JSON object that contains an array of table alterations.\nThe following is the typescript interface for a datatable column and the alterations you can make to it:\n\n\\`\\`\\`typescript\ninterface TableColumn {\n /** Column property */\n prop: string,\n /** Column name */\n name: string,\n /** Column cell type - determines filter type */\n cellType?: 'string' | 'integer' | 'decimal' | 'currency' | 'date' | 'phone',\n /** Whether the column is sortable */\n sortable?: boolean,\n /** Whether the column is filterable */\n filterable?: boolean,\n /** Whether the column is visible */\n visible?: boolean,\n /** Whether the column is resizable */\n resizable?: boolean,\n /** Whether the column is draggable */\n draggable?: boolean,\n /** Column width */\n width?: number,\n /** Column index */\n index?: number,\n}\n\ninterface SortItem {\n /** Column property */\n prop: string,\n /** Sort direction */\n dir: 'asc' | 'desc'\n}\n\ninterface SortState {\n /** The list of sorts */\n sorts: SortItem[]\n}\n\ninterface OrderRecord {\n /** Column property */\n columnProp: string,\n /** Column order, which is the index that it will be placed in the columns array. */\n index: number\n}\n\ninterface OrderState {\n /** The list of column order records */\n columns: OrderRecord[]\n}\n\ninterface WidthState {\n /** The column property that this width alteration applies to */\n columnProp: string\n /** The width of the column. Number is in pixels. */\n width?: number\n /** Whether the column can auto resize. Needs to be false to guarantee a specific width. */\n canAutoResize: boolean\n}\n\ninterface HideColumnState {\n /** The column property that this alteration applies to */\n columnProp: string\n /** Whether the column is hidden */\n hidden: boolean\n}\n\ninterface FilterState {\n /** The column property that this filter applies to */\n columnProp: string,\n /** The filter type based on column cellType */\n filterType: 'text' | 'numeric' | 'date',\n /** The filter operation */\n operation: string,\n /** The filter value (for single value operations) */\n value?: any,\n /** The from value (for range operations like 'between') */\n fromValue?: any,\n /** The to value (for range operations like 'between') */\n toValue?: any\n}\n\ninterface TableAlteration<TType extends string, TState> {\n /**\n * Unique identifier for the alteration.\n */\n id: string\n /**\n * The type of alteration.\n */\n type: TType\n /** The alteration state */\n state: TState\n}\n\n/**\n * Sort alteration for a datatable.\n * \"id\" should always be \"sort\" for this alteration.\n */\ntype SortAlteration = TableAlteration<'sort', SortState>\n\n/**\n * Order alteration for a datatable column.\n *\n * \"id\" should always be \"order\" for this alteration.\n */\ntype OrderAlteration = TableAlteration<'order', OrderState>\n\n/**\n * Width alteration for a datatable column.\n *\n * \"id\" should always be \"width-<prop>\" for this alteration. So, for example, if the column property is \"name\", the id would be \"width-name\".\n */\ntype WidthAlteration = TableAlteration<'width', WidthState>\n\n/**\n * Hide column alteration for a datatable column.\n *\n * \"id\" should always be \"hide-column-<prop>\" for this alteration. So, for example, if the column property is \"name\", the id would be \"hide-column-name\".\n */\ntype HideColumnAlteration = TableAlteration<'hide-column', HideColumnState>\n\n/**\n * Filter alteration for a datatable column.\n * \"id\" should be \"filter--<columnProp>\" for this alteration.\n * For example, if filtering the \"age\" column, the id would be \"filter--age\".\n */\ntype FilterAlteration = TableAlteration<'filter', FilterState>\n\\`\\`\\`\n\n## Filter Operations by Type\n\n### Text Filters (cellType: 'string', 'phone')\n- 'contains': Text contains the value (case-insensitive)\n- 'eq': Text equals the value exactly\n- 'neq': Text does not equal the value\n- 'ncontains': Text does not contain the value\n- 'blank': Field is empty/null\n- 'not-blank': Field is not empty/null\n\n### Numeric Filters (cellType: 'integer', 'decimal', 'currency')\n- 'eq': Equals the value\n- 'gt': Greater than the value\n- 'gte': Greater than or equal to the value\n- 'lt': Less than the value\n- 'lte': Less than or equal to the value\n- 'between': Between fromValue and toValue (inclusive)\n- 'not-between': Not between fromValue and toValue\n- 'blank': Field is empty/null\n- 'not-blank': Field is not empty/null\n\n### Date Filters (cellType: 'date')\n- 'eq': Date equals the value\n- 'gt': Date is after the value\n- 'gte': Date is on or after the value\n- 'lt': Date is before the value\n- 'lte': Date is on or before the value\n- 'between': Date is between fromValue and toValue (inclusive)\n- 'not-between': Date is not between fromValue and toValue\n- 'blank': Field is empty/null\n- 'not-blank': Field is not empty/null\n\n## Examples\n\nFilter age greater than 30:\n\\`\\`\\`json\n{\n \"id\": \"filter--age\",\n \"type\": \"filter\",\n \"state\": {\n \"columnProp\": \"age\",\n \"filterType\": \"numeric\",\n \"operation\": \"gt\",\n \"value\": 30\n }\n}\n\\`\\`\\`\n\nFilter color contains \"red\":\n\\`\\`\\`json\n{\n \"id\": \"filter--color\",\n \"type\": \"filter\",\n \"state\": {\n \"columnProp\": \"color\",\n \"filterType\": \"text\",\n \"operation\": \"contains\",\n \"value\": \"red\"\n }\n}\n\\`\\`\\`\n\nFilter age between 25 and 65:\n\\`\\`\\`json\n{\n \"id\": \"filter--age\",\n \"type\": \"filter\",\n \"state\": {\n \"columnProp\": \"age\",\n \"filterType\": \"numeric\",\n \"operation\": \"between\",\n \"fromValue\": 25,\n \"toValue\": 65\n }\n}\n\\`\\`\\`\n\nSort by name ascending:\n\\`\\`\\`json\n{\n \"id\": \"sort\",\n \"type\": \"sort\",\n \"state\": {\n \"sorts\": [\n {\n \"prop\": \"name\",\n \"dir\": \"asc\"\n }\n ]\n }\n}\n\\`\\`\\`\n\nHide the age column:\n\\`\\`\\`json\n{\n \"id\": \"hide-column-age\",\n \"type\": \"hide-column\",\n \"state\": {\n \"columnProp\": \"age\",\n \"hidden\": true\n }\n}\n\\`\\`\\`\n\nSet name column width to 300 pixels:\n\\`\\`\\`json\n{\n \"id\": \"width-name\",\n \"type\": \"width\",\n \"state\": {\n \"columnProp\": \"name\",\n \"width\": 300,\n \"canAutoResize\": false\n }\n}\n\\`\\`\\`\n\nReorder columns (name first, age second, color third):\n\\`\\`\\`json\n{\n \"id\": \"order\",\n \"type\": \"order\",\n \"state\": {\n \"columns\": [\n { \"columnProp\": \"name\", \"index\": 0 },\n { \"columnProp\": \"age\", \"index\": 1 },\n { \"columnProp\": \"color\", \"index\": 2 }\n ]\n }\n}\n\\`\\`\\`\n`\n\nexport const getUserPrompt = (columns: any[], request: string): string => `\nColumns:\n\\`\\`\\`json\n${JSON.stringify(columns, null, 2)}\n\\`\\`\\`\nRequest: \"${request}\"\n`\n\nexport function parseResponse(\n responseContent: string,\n responseFormat: { type: string } | undefined,\n) {\n if (responseFormat?.type === 'json_object') {\n return JSON.parse(responseContent)\n }\n\n // Parse the JSON string to an object, which is in the string between the code blocks.\n // So, need to find the first and last code block markers.\n const startIndex = responseContent.indexOf('```json') + '```json'.length\n const endIndex = responseContent.lastIndexOf('```')\n const alterations = responseContent.substring(startIndex, endIndex).trim()\n // console.log('Alterations:', alterations)\n\n return JSON.parse(alterations)\n}\n\nexport const THESEAM_DATATABLE_PROMPTER_PROVIDER =\n new InjectionToken<AiProvider>('TheSeamDatatablePrompterProvider')\n","import { ChangeDetectorRef, Component, inject, Input } from '@angular/core'\nimport { AsyncPipe, JsonPipe, NgForOf, NgIf } from '@angular/common'\nimport {\n FormControl,\n FormGroup,\n ReactiveFormsModule,\n Validators,\n} from '@angular/forms'\n\nimport {\n BehaviorSubject,\n combineLatest,\n map,\n Observable,\n of,\n shareReplay,\n startWith,\n switchMap,\n tap,\n} from 'rxjs'\nimport {\n ColumnsAlterationState,\n DatatableComponent,\n DatatablePreferencesService,\n EMPTY_DATATABLE_PREFERENCES,\n mapColumnsAlterationsStates,\n THESEAM_DATATABLE_PREFERENCES_ACCESSOR,\n} from '@theseam/ui-common/datatable'\nimport { TheSeamLoadingModule } from '@theseam/ui-common/loading'\nimport { TheSeamRichTextModule } from '@theseam/ui-common/rich-text'\nimport { TheSeamFormFieldModule } from '@theseam/ui-common/form-field'\nimport { TheSeamButtonsModule } from '@theseam/ui-common/buttons'\nimport {\n AlterationDisplayItem,\n AlterationsDiffComponent,\n} from '@theseam/ui-common/datatable-alterations-display'\n\nimport {\n assistantPrompt,\n getUserPrompt,\n parseResponse,\n THESEAM_DATATABLE_PROMPTER_PROVIDER,\n} from './datatable-prompter-prompt-provider'\n\n@Component({\n selector: 'seam-datatable-prompter',\n templateUrl: './datatable-prompter.component.html',\n styleUrls: ['./datatable-prompter.component.scss'],\n imports: [\n ReactiveFormsModule,\n AsyncPipe,\n JsonPipe,\n NgForOf,\n NgIf,\n TheSeamLoadingModule,\n TheSeamRichTextModule,\n TheSeamFormFieldModule,\n TheSeamButtonsModule,\n AlterationsDiffComponent,\n ],\n})\nexport class TheSeamDatatablePrompterComponent {\n // cdr = inject(ChangeDetectorRef)\n\n private readonly _prefsAccessor = inject(\n THESEAM_DATATABLE_PREFERENCES_ACCESSOR,\n { optional: true },\n )\n private readonly _dtPrefsService = inject(DatatablePreferencesService)\n private readonly _aiProvider = inject(THESEAM_DATATABLE_PROMPTER_PROVIDER, {\n optional: true,\n })\n\n readonly _loadingSubject = new BehaviorSubject<boolean>(false)\n readonly _altsDataSubject = new BehaviorSubject<\n | {\n currentItems: AlterationDisplayItem[]\n pendingItems: AlterationDisplayItem[]\n }\n | undefined\n >(undefined)\n\n public readonly loading$ = this._loadingSubject.asObservable()\n\n @Input() diffMode: 'auto' | 'manual' = 'auto'\n @Input() compact = true\n\n @Input()\n set prompt(value: string | undefined | null) {\n if (value) {\n this._form.controls.prompt.setValue(value)\n } else {\n this._form.controls.prompt.setValue('Sort color descending order')\n }\n }\n\n @Input()\n set datatable(value: DatatableComponent | undefined | null) {\n this._datatableSubject.next(value)\n }\n get datatable(): DatatableComponent | undefined | null {\n return this._datatableSubject.value\n }\n private _datatableSubject = new BehaviorSubject<\n DatatableComponent | undefined | null\n >(null)\n\n @Input() showAlts = true\n\n readonly _form = new FormGroup({\n prompt: new FormControl<string | null>('Sort color descending order', [\n Validators.required,\n ]),\n })\n\n _alterations$: Observable<ColumnsAlterationState[]> = this._datatableSubject\n .asObservable()\n .pipe(\n switchMap((dt): Observable<DatatableComponent | null | undefined> => {\n if (!dt) {\n return of(dt)\n }\n return (dt as any)._columnsAlterationsManager.changes.pipe(\n startWith(undefined),\n map(() => dt),\n )\n }),\n switchMap((datatable) => {\n if (!datatable) {\n return of([] as ColumnsAlterationState[])\n }\n const key = datatable.preferencesKey\n if (!key) {\n // eslint-disable-next-line no-console\n console.warn(\n 'No preferences key set on datatable, returning empty alterations.',\n )\n return of([] as ColumnsAlterationState[])\n }\n\n return (\n this._dtPrefsService.preferences(key).pipe(\n switchMap((prefs) => {\n // console.log('~~~~Current preferences:', prefs)\n if (!prefs) {\n return of(\n JSON.parse(JSON.stringify(EMPTY_DATATABLE_PREFERENCES))\n .alterations as ColumnsAlterationState[],\n )\n }\n // return of(JSON.parse(prefs).alterations as ColumnsAlterationState[])\n return of(prefs.alterations as ColumnsAlterationState[])\n }),\n ) ?? of([] as ColumnsAlterationState[])\n )\n }),\n // tap(v => console.log('%cAlterations:', 'color: limegreen;', v)),\n )\n\n _alterationsDisplayItems$: Observable<AlterationDisplayItem[]> =\n this._alterations$.pipe(\n switchMap((alterations) => {\n console.log('~~~~~Current alterations:', alterations)\n if (!alterations || alterations.length === 0) {\n return of([] as AlterationDisplayItem[])\n }\n const alts = mapColumnsAlterationsStates(alterations)\n console.log('~~~~~Mapped alterations:', alts)\n return of(alts.map((a) => a.toDisplayItem()))\n }),\n shareReplay({ bufferSize: 1, refCount: true }),\n )\n\n _pendingAlterationsSubject = new BehaviorSubject<ColumnsAlterationState[]>([])\n _pendingAlterationsDisplayItems$: Observable<AlterationDisplayItem[]> =\n this._pendingAlterationsSubject.asObservable().pipe(\n switchMap((pending) => {\n if (!pending || pending.length === 0) {\n return of([] as AlterationDisplayItem[])\n }\n const alts = mapColumnsAlterationsStates(pending)\n console.log('~~~~~Mapped alterations2:', alts)\n return of(alts.map((a) => a.toDisplayItem()))\n }),\n shareReplay({ bufferSize: 1, refCount: true }),\n )\n\n _onSubmit() {\n console.log('Submitting prompt:', this._form.value)\n if (this._form.invalid) {\n return\n }\n if (this._loadingSubject.value) {\n console.warn('Already loading, ignoring submit.')\n return\n }\n\n const prompt = this._form.value.prompt\n if (!prompt) {\n return\n }\n console.log('datatable', this._datatableSubject.value)\n const columns = (\n this._datatableSubject.value?.ngxDatatable?.columns || []\n ).map((col) => ({\n prop: col.prop,\n name: col.name,\n cellType: (col as any).cellType || 'string',\n sortable: col.sortable,\n filterable: true,\n visible: true,\n resizable: col.resizeable,\n draggable: col.draggable,\n }))\n\n console.log('columns', columns)\n const userPrompt = getUserPrompt(columns, prompt)\n console.log('userPrompt', userPrompt)\n\n this._loadingSubject.next(true)\n if (!this._aiProvider) {\n console.error('No AI provider configured, cannot submit prompt.')\n this._loadingSubject.next(false)\n return\n }\n this._aiProvider\n .chat([\n { role: 'system', content: assistantPrompt },\n { role: 'user', content: userPrompt },\n ])\n .then(async (response) => {\n const alterations = parseResponse(response.content, undefined)\n // this._form.reset()\n console.log('Received alterations:', alterations)\n const datatable = this._datatableSubject.value\n if (!datatable) {\n console.error('No datatable found to apply alterations to.')\n return\n }\n\n const key = this.datatable!.preferencesKey as string\n\n const before = await this._prefsAccessor?.get(key).toPromise()\n console.log('Current preferences before update:', before)\n\n const _apply = async () => {\n console.log('Preferences updated successfully.')\n const _cols = this.datatable!.ngxDatatable!.columns\n const cols = [..._cols]\n console.log('this.datatable!.columns', cols)\n\n const after = await this._prefsAccessor?.get(key).toPromise()\n let _after = (JSON.parse(after || '{}').alterations ||\n []) as ColumnsAlterationState[]\n if (!Array.isArray(_after)) {\n _after = [_after]\n }\n\n const mgr = (this.datatable as any)._columnsAlterationsManager\n console.log('_columnsAlterationsManager', mgr, mgr.get())\n const alts = mapColumnsAlterationsStates(_after)\n console.log('Mapped alterations:', alts)\n const columnsBefore = JSON.parse(\n JSON.stringify(\n this.datatable!.ngxDatatable!.columns.map((x) => x.prop),\n ),\n )\n console.log('Columns before applying alterations:', columnsBefore)\n for (const a of alts) {\n console.log('Applying alteration:', a)\n a.apply(cols, this.datatable!)\n }\n console.log('Current preferences after update:', after)\n console.log(_after)\n\n this.datatable!.columns = [...cols]\n const columnsAfter = JSON.parse(\n JSON.stringify(\n this.datatable!.ngxDatatable!.columns.map((x) => x.prop),\n ),\n )\n console.log('Columns after applying alterations:', columnsAfter)\n mgr.add(alts)\n datatable._cdr.detectChanges()\n\n this._pendingAlterationsSubject.next(_after)\n }\n\n this._prefsAccessor\n ?.update(\n key,\n JSON.stringify({\n version: 2,\n alterations,\n }),\n )\n .subscribe(async () => {\n // TODO: Cleanup. This is a hack to ensure the datatable updates after the preferences are set.\n await _apply()\n datatable.rows = [...datatable.rows]\n datatable._cdr.detectChanges()\n await _apply()\n\n this._loadingSubject.next(false)\n })\n })\n .catch((err) => {\n console.error('Error submitting prompt:', err)\n this._loadingSubject.next(false)\n })\n }\n}\n","<div class=\"d-block border rounded border-lightgray\">\n <div\n [formGroup]=\"_form\"\n (ngSubmit)=\"_onSubmit()\"\n class=\"d-block position-relative\"\n >\n <div>\n <div class=\"p-1\">\n <!-- <textarea formControlName=\"prompt\" style=\"width: 800px; height: 100px;\"></textarea> -->\n <seam-form-field [numPaddingErrors]=\"0\">\n <seam-rich-text\n seamInput\n formControlName=\"prompt\"\n placeholder=\"Describe what you want to apply to the datatable.\"\n [rows]=\"3\"\n [resizable]=\"false\"\n [disableRichText]=\"true\"\n ></seam-rich-text>\n </seam-form-field>\n </div>\n <div class=\"p-1\">\n <button\n class=\"mr-1\"\n type=\"submit\"\n seamButton\n theme=\"primary\"\n size=\"sm\"\n (click)=\"_onSubmit()\"\n >\n Submit\n </button>\n <button seamButton theme=\"lightgray\" size=\"sm\" (click)=\"_form.reset()\">\n Reset\n </button>\n </div>\n </div>\n <div\n *ngIf=\"loading$ | async\"\n class=\"d-block position-absolute\"\n style=\"top: 0; left: 0; right: 0; bottom: 0\"\n >\n <seam-loading></seam-loading>\n </div>\n </div>\n\n <div class=\"p-2\" *ngIf=\"showAlts\">\n <div>Active Alterations</div>\n <div class=\"p-2 border rounded bg-lightgray\">\n <!-- {{ _alterations$ | async | json }} -->\n <div *ngFor=\"let alteration of _alterations$ | async; let last = last\">\n <div\n class=\"d-flex align-items-center border border-dark rounded p-1\"\n [class.mb-1]=\"!last\"\n >\n <span class=\"badge bg-secondary\">{{ alteration.type }}</span>\n <!-- <span class=\"badge bg-primary\">{{ alteration.label }}</span> -->\n <!-- <div>\n {{ alteration.value | json }}\n </div> -->\n <div *ngIf=\"alteration.type === 'sort'\">\n <div class=\"d-flex flex-column\">\n <div\n *ngFor=\"let sort of alteration.state.sorts; let last = last\"\n [class.mb-1]=\"!last\"\n >\n <span class=\"badge bg-lightgray\"\n >{{ sort.prop }} ({{ sort.dir }})</span\n >\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <seam-alterations-diff\n [currentItems]=\"(_alterationsDisplayItems$ | async) ?? []\"\n [pendingItems]=\"(_pendingAlterationsDisplayItems$ | async) ?? []\"\n [compact]=\"compact\"\n [diffMode]=\"diffMode\"\n ></seam-alterations-diff>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i4","i2","i5"],"mappings":"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"}
@@ -1,14 +1,16 @@
1
1
  import { ApolloLink, NetworkStatus, Observable as Observable$1 } from '@apollo/client/core';
2
2
  import { print, visit as visit$1, parse, BREAK as BREAK$1, parseValue, Kind, valueFromASTUntyped } from 'graphql';
3
- import { hasProperty, notNullOrUndefined, isNullOrUndefined, withoutProperty, wrapIntoObservable, withoutProperties } from '@theseam/ui-common/utils';
4
3
  import { visit, BREAK } from 'graphql/language';
5
4
  import * as i0 from '@angular/core';
6
5
  import { isDevMode, InjectionToken, Optional, Inject, Injectable, EventEmitter } from '@angular/core';
6
+ import { hasProperty, notNullOrUndefined, isNullOrUndefined, withoutProperty, wrapIntoObservable, withoutProperties } from '@theseam/ui-common/utils';
7
7
  import { Observable, EMPTY, from, defer, of, combineLatest, Subscription, Subject, BehaviorSubject, isObservable } from 'rxjs';
8
8
  import { switchMap, tap, take, concatMap, filter, toArray, map, auditTime, distinctUntilChanged, finalize, catchError, shareReplay, startWith, skip } from 'rxjs/operators';
9
9
  import * as i1 from 'apollo-angular';
10
10
  import { gql, provideApollo } from 'apollo-angular';
11
11
  import { THESEAM_COLUMNS_DATA_FILTER_DATE_TEXT_SEARCH_TYPES, getFormattedDateForComparison, THESEAM_COLUMNS_DATA_FILTER_DATE_RANGE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_RANGE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_TEXT_SEARCH_TYPES } from '@theseam/ui-common/datatable';
12
+ import { faFileCsv } from '@fortawesome/free-solid-svg-icons';
13
+ import FileSaver from 'file-saver';
12
14
  import { concat, InMemoryCache } from '@apollo/client';
13
15
 
14
16
  /**
@@ -44,35 +46,15 @@ function logQueryLink(inner, options) {
44
46
  return ApolloLink.from([beforeLink, inner, afterLink]);
45
47
  }
46
48
 
47
- class GQLDirection {
48
- direction;
49
- constructor(direction) {
50
- this.direction = direction;
51
- }
52
- static ASC = new GQLDirection('ASC');
53
- static DESC = new GQLDirection('DESC');
54
- }
55
-
56
- var HintsKind;
57
- (function (HintsKind) {
58
- HintsKind["OperationDefinition"] = "OperationDefinition";
59
- HintsKind["Field"] = "Field";
60
- HintsKind["VariableDefinition"] = "VariableDefinition";
61
- HintsKind["Variable"] = "Variable";
62
- HintsKind["Argument"] = "Argument";
63
- })(HintsKind || (HintsKind = {}));
64
-
65
- const DEFAULT_TO_REMOVE_ON_UNDEFINED = ['where', 'order'];
66
-
67
- class GQLVariable {
68
- name;
69
- type;
70
- constructor(name, type) {
71
- this.name = name;
72
- this.type = type;
73
- }
74
- }
75
-
49
+ /**
50
+ * Checks whether a GraphQL document or value node contains a reference to
51
+ * the named variable.
52
+ *
53
+ * This includes references inside variable definitions — a variable that is
54
+ * defined but not used as an argument will still be found. This behavior is
55
+ * relied on by `removeIfNotUsed` processing to avoid removing variables that
56
+ * may be needed after a later inline step.
57
+ */
76
58
  function containsVariable(node, variableName) {
77
59
  let found = false;
78
60
  visit(node, {
@@ -86,10 +68,32 @@ function containsVariable(node, variableName) {
86
68
  return found;
87
69
  }
88
70
 
71
+ /**
72
+ * Creates a variable reference marker for use in filter objects that will be
73
+ * passed to `toGQL` and inlined into a query.
74
+ *
75
+ * When `toGQL` encounters an object with a `gqlVar` property, it emits the
76
+ * value as-is (e.g. `$search`), producing a GraphQL variable reference in the
77
+ * output rather than a string literal.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const filter = { name: { contains: gqlVar('search') } }
82
+ * // toGQL(filter) → '{name: {contains: $search}}'
83
+ * ```
84
+ */
89
85
  function gqlVar(varName) {
90
86
  return { gqlVar: `$${varName}` };
91
87
  }
92
88
 
89
+ /**
90
+ * Replaces all references to a variable in the query body with a literal
91
+ * value. If the value represents `undefined`, the variable references are
92
+ * removed from the query instead.
93
+ *
94
+ * This does not remove the variable definition — use `removeVariableDefinition`
95
+ * separately if needed.
96
+ */
93
97
  function inlineVariable(query, variableName, variableValue) {
94
98
  // return visit(query, {
95
99
  // VariableDefinition(node) {
@@ -163,6 +167,35 @@ function parseComments(ast) {
163
167
  return comments;
164
168
  }
165
169
 
170
+ class GQLDirection {
171
+ direction;
172
+ constructor(direction) {
173
+ this.direction = direction;
174
+ }
175
+ static ASC = new GQLDirection('ASC');
176
+ static DESC = new GQLDirection('DESC');
177
+ }
178
+
179
+ var HintsKind;
180
+ (function (HintsKind) {
181
+ HintsKind["OperationDefinition"] = "OperationDefinition";
182
+ HintsKind["Field"] = "Field";
183
+ HintsKind["VariableDefinition"] = "VariableDefinition";
184
+ HintsKind["Variable"] = "Variable";
185
+ HintsKind["Argument"] = "Argument";
186
+ })(HintsKind || (HintsKind = {}));
187
+
188
+ const DEFAULT_TO_REMOVE_ON_UNDEFINED = ['where', 'order'];
189
+
190
+ class GQLVariable {
191
+ name;
192
+ type;
193
+ constructor(name, type) {
194
+ this.name = name;
195
+ this.type = type;
196
+ }
197
+ }
198
+
166
199
  const HINT_PREFIX_REGEX = /^\s*@gql-hint:.+/;
167
200
  const HINT_NAMES_CAPTURE_REGEX = /^\s*@gql-hint:([a-zA-z-\d\s]+)$/;
168
201
  /**
@@ -268,6 +301,13 @@ function parseHints(ast) {
268
301
  .filter(notNullOrUndefined);
269
302
  }
270
303
 
304
+ /**
305
+ * Removes a variable's definition from the query (e.g. `$where: String` in the
306
+ * operation signature). Does not remove argument references to that variable in
307
+ * the query body.
308
+ *
309
+ * To remove both the definition and argument references, use `removeVariable`.
310
+ */
271
311
  function removeVariableDefinition(query, variableName) {
272
312
  return visit$1(query, {
273
313
  VariableDefinition: {
@@ -281,6 +321,14 @@ function removeVariableDefinition(query, variableName) {
281
321
  });
282
322
  }
283
323
 
324
+ /**
325
+ * Removes variable definitions from the specified operation when the variable
326
+ * does not have a corresponding value in the provided variables object (i.e.
327
+ * the value is `null` or `undefined`).
328
+ *
329
+ * Unlike `removeVariable`, this only removes the definitions — it does not
330
+ * remove argument references in the query body.
331
+ */
284
332
  function removeVariableDefinitionsNotDefined(query, node, variables) {
285
333
  return visit$1(query, {
286
334
  OperationDefinition(opDef) {
@@ -298,6 +346,14 @@ function removeVariableDefinitionsNotDefined(query, node, variables) {
298
346
  });
299
347
  }
300
348
 
349
+ /**
350
+ * Removes a variable from the query by removing both the variable definition
351
+ * (e.g. `$where: String` in the operation signature) and argument references
352
+ * with the same name (e.g. `where: $where` in the field arguments).
353
+ *
354
+ * To remove only the definition without touching arguments, use
355
+ * `removeVariableDefinition`.
356
+ */
301
357
  function removeVariable(query, variableName) {
302
358
  return visit$1(query, {
303
359
  VariableDefinition: {
@@ -468,70 +524,120 @@ const removeNotDefinedHintDef = {
468
524
  // ]
469
525
 
470
526
  /**
471
- * Apollo link that transforms GraphQL operations before they are sent.
527
+ * Transforms a GraphQL query and its variables according to the provided
528
+ * processing configuration.
472
529
  *
473
530
  * Two mechanisms are supported and can be combined freely:
474
531
  *
475
- * **Hint-based** — place `# @gql-hint: <name>` comments directly in the query.
476
- * Supported hints:
477
- * - `remove-not-defined` on the operation definition: removes every variable
478
- * whose value is null/undefined (definition + argument usage).
479
- * - `inline-variable` on a variable definition or usage: substitutes the
480
- * variable's current value directly into the query AST and removes it from
481
- * the variables map.
532
+ * **Hint-based** — `# @gql-hint: <name>` comments in the query.
533
+ * - `remove-not-defined`: removes variables whose value is null/undefined.
534
+ * - `inline-variable`: substitutes variable values directly into the AST.
482
535
  *
483
- * **Config-based** — pass a `QueryProcessingConfig` via Apollo context under
484
- * the key `queryProcessingConfig`. Supported options:
485
- * - `variables.removeIfNotDefined`: remove named variables when null/undefined.
486
- * - `variables.removeIfNotUsed`: remove named variable definitions when the
487
- * variable is not referenced anywhere in the (possibly already-transformed)
488
- * query body.
489
- * - `variables.inline`: inline named variables into the query AST.
536
+ * **Config-based** — via `QueryProcessingConfig`:
537
+ * - `removeIfNotDefined`: remove named variables when null/undefined.
538
+ * - `removeIfNotUsed`: remove named variable definitions when unreferenced.
539
+ * - `inline`: inline named variables into the query AST.
540
+ * - `orderTiebreaker`: append a fallback sort field for deterministic pagination.
490
541
  *
491
- * Hints are applied first, then config-based processing.
542
+ * Hints are applied first, then config-based processing, then cleanup.
492
543
  */
493
- const queryProcessingLink = new ApolloLink((operation, forward) => {
494
- const context = operation.getContext();
495
- const queryProcessingConfig = context.queryProcessingConfig ?? {};
496
- // Reparse to ensure token/comment info is present for hint parsing.
497
- let _ast = parseAst(operation.query);
544
+ function processGql(query, variables, queryProcessingConfig) {
545
+ let _ast = parseAst(query);
546
+ let _variables = { ...variables };
547
+ // ---- Hint: remove-not-defined ------------------------------------------
498
548
  const rules = parseHints(_ast);
499
- // ---- Hint: remove-not-defined ----------------------------------------
500
549
  for (const hintsToken of hintsTokensContainingHint(rules, removeNotDefinedHintDef.name)) {
501
- const result = removeNotDefinedHintDef.transformer({ query: _ast, variables: operation.variables }, hintsToken);
550
+ const result = removeNotDefinedHintDef.transformer({ query: _ast, variables: _variables }, hintsToken);
502
551
  _ast = result.query;
503
- operation.variables = result.variables;
552
+ _variables = result.variables;
504
553
  }
505
- // ---- Hint: inline-variable --------------------------------------------
554
+ // ---- Hint: inline-variable ---------------------------------------------
506
555
  for (const hintsToken of hintsTokensContainingHint(rules, inlineVariableHintDef.name)) {
507
- const result = inlineVariableHintDef.transformer({ query: _ast, variables: operation.variables }, hintsToken);
556
+ const result = inlineVariableHintDef.transformer({ query: _ast, variables: _variables }, hintsToken);
508
557
  _ast = result.query;
509
- operation.variables = result.variables;
558
+ _variables = result.variables;
510
559
  }
511
- // ---- Config: removeIfNotDefined ---------------------------------------
560
+ // ---- Config: removeIfNotDefined ----------------------------------------
512
561
  for (const varName of queryProcessingConfig?.variables?.removeIfNotDefined ??
513
562
  []) {
514
- if (isNullOrUndefined(operation.variables[varName])) {
563
+ if (isNullOrUndefined(_variables[varName])) {
515
564
  _ast = removeVariable(_ast, varName);
516
565
  }
517
566
  }
518
- // ---- Config: removeIfNotUsed -----------------------------------------
519
- // Intentionally runs after removeIfNotDefined so that variables which were
520
- // only referenced inside another (now-removed) variable can be cleaned up.
567
+ // ---- Config: removeIfNotUsed -------------------------------------------
521
568
  for (const varName of queryProcessingConfig?.variables?.removeIfNotUsed ??
522
569
  []) {
523
570
  if (!containsVariable(_ast, varName)) {
524
571
  _ast = removeVariable(_ast, varName);
525
572
  }
526
573
  }
527
- // ---- Config: inline --------------------------------------------------
574
+ // ---- Config: inline ----------------------------------------------------
528
575
  for (const varName of queryProcessingConfig?.variables?.inline ?? []) {
529
- const varValue = operation.variables[varName];
530
- operation.variables = withoutProperty(operation.variables, varName);
576
+ const varValue = _variables[varName];
577
+ _variables = withoutProperty(_variables, varName);
531
578
  _ast = removeVariableDefinition(_ast, varName);
532
579
  _ast = inlineVariable(_ast, varName, parseValue(toGQL(varValue)));
533
580
  }
534
- operation.query = _ast;
581
+ // ---- Config: orderTiebreaker -------------------------------------------
582
+ const orderTiebreaker = queryProcessingConfig?.variables?.orderTiebreaker;
583
+ if (typeof orderTiebreaker === 'string' && orderTiebreaker.length > 0) {
584
+ const order = _variables['order'];
585
+ if (!isNullOrUndefined(order) && Array.isArray(order)) {
586
+ const idx = order.findIndex((x) => x[orderTiebreaker] !== undefined);
587
+ if (idx === -1) {
588
+ _variables['order'] = [...order, { [orderTiebreaker]: 'DESC' }];
589
+ }
590
+ }
591
+ }
592
+ // ---- Cleanup: empty where ----------------------------------------------
593
+ // Targets inlined filter results like `where: { and: [] }` where the
594
+ // datatable's automated filter merging produced an empty array. We
595
+ // intentionally do NOT match deeper nesting (e.g. `where: { status: { in: [] } }`)
596
+ // — an empty condition at that level likely indicates a real bug in the
597
+ // filter code that should surface as an error.
598
+ _ast = visit$1(_ast, {
599
+ Argument(node) {
600
+ if (node.name.value === 'where' &&
601
+ node.value?.fields?.length &&
602
+ node.value?.fields[0]?.value?.values?.length === 0) {
603
+ return null;
604
+ }
605
+ },
606
+ });
607
+ return { query: _ast, variables: _variables };
608
+ }
609
+
610
+ /**
611
+ * Apollo link that transforms GraphQL operations before they are sent.
612
+ *
613
+ * Two mechanisms are supported and can be combined freely:
614
+ *
615
+ * **Hint-based** — place `# @gql-hint: <name>` comments directly in the query.
616
+ * Supported hints:
617
+ * - `remove-not-defined` on the operation definition: removes every variable
618
+ * whose value is null/undefined (definition + argument usage).
619
+ * - `inline-variable` on a variable definition or usage: substitutes the
620
+ * variable's current value directly into the query AST and removes it from
621
+ * the variables map.
622
+ *
623
+ * **Config-based** — pass a `QueryProcessingConfig` via Apollo context under
624
+ * the key `queryProcessingConfig`. Supported options:
625
+ * - `variables.removeIfNotDefined`: remove named variables when null/undefined.
626
+ * - `variables.removeIfNotUsed`: remove named variable definitions when the
627
+ * variable is not referenced anywhere in the (possibly already-transformed)
628
+ * query body.
629
+ * - `variables.inline`: inline named variables into the query AST.
630
+ * - `variables.orderTiebreaker`: append a fallback sort field for deterministic
631
+ * pagination.
632
+ *
633
+ * Hints are applied first, then config-based processing.
634
+ */
635
+ const queryProcessingLink = new ApolloLink((operation, forward) => {
636
+ const context = operation.getContext();
637
+ const queryProcessingConfig = context.queryProcessingConfig ?? {};
638
+ const result = processGql(operation.query, operation.variables, queryProcessingConfig);
639
+ operation.query = result.query;
640
+ operation.variables = result.variables;
535
641
  return forward(operation);
536
642
  });
537
643
 
@@ -990,6 +1096,20 @@ class DatatableGraphQLQueryRef {
990
1096
  // (including any disablePaging requery).
991
1097
  switchMap((v) => hasEmittedSubject.pipe(map((hasEmitted) => (hasEmitted ? v : true)))));
992
1098
  }
1099
+ /**
1100
+ * Returns an observable of mapped rows from the query result.
1101
+ *
1102
+ * The mapper transforms the raw GraphQL response data into the row format
1103
+ * the datatable expects, and provides the total count for pagination.
1104
+ *
1105
+ * @example
1106
+ * ```typescript
1107
+ * this.rows$ = this._queryRef.rows((data) => ({
1108
+ * rows: data.items.items,
1109
+ * totalCount: data.items.totalCount,
1110
+ * }))
1111
+ * ```
1112
+ */
993
1113
  rows(mapper) {
994
1114
  return this._rowsObservable(mapper);
995
1115
  }
@@ -1513,6 +1633,80 @@ const mapSearchTextColumnsDataFilterStateToGql = (filterState, context) => {
1513
1633
  return filter;
1514
1634
  };
1515
1635
 
1636
+ /**
1637
+ * Abstract transport for server-side datatable exports.
1638
+ *
1639
+ * THIS SHOULD BE IMPLEMENTED AND PROVIDED BY THE APPLICATION USING 'ui-common'.
1640
+ *
1641
+ * Example:
1642
+ * ```ts
1643
+ * bootstrapApplication(AppComponent, {
1644
+ * providers: [
1645
+ * provideDatatableExportTransport(AppDatatableExportTransport),
1646
+ * ],
1647
+ * })
1648
+ * ```
1649
+ */
1650
+ class DatatableExportTransport {
1651
+ }
1652
+ /**
1653
+ * Register the application's `DatatableExportTransport` implementation.
1654
+ *
1655
+ * ```ts
1656
+ * bootstrapApplication(AppComponent, {
1657
+ * providers: [
1658
+ * provideDatatableExportTransport(AppDatatableExportTransport),
1659
+ * ],
1660
+ * })
1661
+ * ```
1662
+ */
1663
+ function provideDatatableExportTransport(transportType) {
1664
+ return { provide: DatatableExportTransport, useClass: transportType };
1665
+ }
1666
+
1667
+ class DatatableGqlDataExporter {
1668
+ _exporterName;
1669
+ _exporterLabel;
1670
+ _columns;
1671
+ _queryRef;
1672
+ _transport;
1673
+ _exportType;
1674
+ get name() {
1675
+ return this._exporterName;
1676
+ }
1677
+ get label() {
1678
+ return this._exporterLabel;
1679
+ }
1680
+ icon = faFileCsv;
1681
+ skipDataMapping = true;
1682
+ constructor(_exporterName, _exporterLabel, _columns, _queryRef, _transport, _exportType) {
1683
+ this._exporterName = _exporterName;
1684
+ this._exporterLabel = _exporterLabel;
1685
+ this._columns = _columns;
1686
+ this._queryRef = _queryRef;
1687
+ this._transport = _transport;
1688
+ this._exportType = _exportType;
1689
+ }
1690
+ export(data) {
1691
+ const options = this._queryRef.getOptions();
1692
+ const { query, variables } = processGql(options.query, this._queryRef.getVariables(), this._queryRef.getQueryProcessingConfig() ?? { variables: {} });
1693
+ const operationName = query.definitions.find((d) => d.kind === 'OperationDefinition')?.name?.value ?? '';
1694
+ const payload = {
1695
+ graphQlQuery: {
1696
+ queryString: print(query),
1697
+ queryVariables: variables,
1698
+ operationName,
1699
+ columns: this._columns,
1700
+ },
1701
+ exportType: this._exportType,
1702
+ };
1703
+ return this._transport.export(payload).pipe(tap((file) => FileSaver.saveAs(file)), map(() => true), catchError((err) => {
1704
+ console.error(err);
1705
+ return of(false);
1706
+ }));
1707
+ }
1708
+ }
1709
+
1516
1710
  const baseSchemaFragment = gql `
1517
1711
  input ComparableInt32OperationFilterInput {
1518
1712
  eq: Int
@@ -2168,5 +2362,5 @@ const SIMPLE_GQL_TEST_SEARCH_QUERY = gql `
2168
2362
  * Generated bundle index. Do not edit.
2169
2363
  */
2170
2364
 
2171
- export { DATATABLE_GRAPHQL_SERVICE_CONFIG, DEFAULT_PAGE_SIZE, DEFAULT_TO_REMOVE_ON_UNDEFINED, DatatableGraphQLQueryRef, DatatableGraphqlService, GQLDirection, GQLVariable, HINT_NAMES_CAPTURE_REGEX, HINT_PREFIX_REGEX, HintsKind, MAX_ERROR_RECOVERY_ATTEMPTS, MockDatatable, SIMPLE_GQL_TEST_QUERY, SIMPLE_GQL_TEST_SEARCH_QUERY, baseSchemaFragment, checkRecordsHaveValue, containsVariable, createHintsToken, createMockApolloTestingProvider, createSimpleGqlTestRecord, createSimpleGqlTestRoot, createSortsMapper, filterWhere, filteredResults, getHintsToken, getPageInfo, getTokenAppliesTo, gqlVar, hintNamesFromHintToken, hintsTokensContainingHint, inlineVariable, inlineVariableHintDef, inlineVariableTransformer, isCommentToken, isHintToken, isInlineComment, logQueryLink, mapFilterStates, mapSearchDateColumnsDataFilterStateToGql, mapSearchNumericColumnsDataFilterStateToGql, mapSearchTextColumnsDataFilterStateToGql, mockGraphQLLink, observeRowsWithGqlInputsHandling, parseAst, parseComments, parseHints, queryProcessingLink, removeNotDefinedHintDef, removeNotDefinedTransformer, removeVariable, removeVariableDefinition, removeVariableDefinitionsNotDefined, skipAndTake, sortItems, toGQL };
2365
+ export { DATATABLE_GRAPHQL_SERVICE_CONFIG, DEFAULT_PAGE_SIZE, DEFAULT_TO_REMOVE_ON_UNDEFINED, DatatableExportTransport, DatatableGqlDataExporter, DatatableGraphQLQueryRef, DatatableGraphqlService, GQLDirection, GQLVariable, HINT_NAMES_CAPTURE_REGEX, HINT_PREFIX_REGEX, HintsKind, MAX_ERROR_RECOVERY_ATTEMPTS, MockDatatable, SIMPLE_GQL_TEST_QUERY, SIMPLE_GQL_TEST_SEARCH_QUERY, baseSchemaFragment, checkRecordsHaveValue, containsVariable, createHintsToken, createMockApolloTestingProvider, createSimpleGqlTestRecord, createSimpleGqlTestRoot, createSortsMapper, filterWhere, filteredResults, getHintsToken, getPageInfo, getTokenAppliesTo, gqlVar, hintNamesFromHintToken, hintsTokensContainingHint, inlineVariable, inlineVariableHintDef, inlineVariableTransformer, isCommentToken, isHintToken, isInlineComment, logQueryLink, mapFilterStates, mapSearchDateColumnsDataFilterStateToGql, mapSearchNumericColumnsDataFilterStateToGql, mapSearchTextColumnsDataFilterStateToGql, mockGraphQLLink, observeRowsWithGqlInputsHandling, parseAst, parseComments, parseHints, processGql, provideDatatableExportTransport, queryProcessingLink, removeNotDefinedHintDef, removeNotDefinedTransformer, removeVariable, removeVariableDefinition, removeVariableDefinitionsNotDefined, skipAndTake, sortItems, toGQL };
2172
2366
  //# sourceMappingURL=theseam-ui-common-graphql.mjs.map