@qwanyx/stack 0.2.6 → 0.2.9

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,53 @@
1
+ import type { ApiConfig, QueryParams } from '../types';
2
+ /**
3
+ * Generic API Client
4
+ * Framework-agnostic HTTP client for any API
5
+ */
6
+ export declare class ApiClient {
7
+ private config;
8
+ constructor(config: ApiConfig);
9
+ /**
10
+ * Build query string from params
11
+ */
12
+ private buildQueryString;
13
+ /**
14
+ * Make HTTP request
15
+ */
16
+ private request;
17
+ /**
18
+ * GET request
19
+ */
20
+ get<T = any>(endpoint: string, params?: QueryParams): Promise<T>;
21
+ /**
22
+ * POST request
23
+ */
24
+ post<T = any>(endpoint: string, body?: any, params?: QueryParams): Promise<T>;
25
+ /**
26
+ * PUT request
27
+ */
28
+ put<T = any>(endpoint: string, body?: any, params?: QueryParams): Promise<T>;
29
+ /**
30
+ * PATCH request
31
+ */
32
+ patch<T = any>(endpoint: string, body?: any, params?: QueryParams): Promise<T>;
33
+ /**
34
+ * DELETE request
35
+ */
36
+ delete<T = any>(endpoint: string, params?: QueryParams): Promise<T>;
37
+ /**
38
+ * Update base URL
39
+ */
40
+ setBaseUrl(baseUrl: string): void;
41
+ /**
42
+ * Get current base URL
43
+ */
44
+ getBaseUrl(): string;
45
+ }
46
+ /**
47
+ * Initialize the API client
48
+ */
49
+ export declare function initializeApiClient(config: ApiConfig): ApiClient;
50
+ /**
51
+ * Get the API client instance
52
+ */
53
+ export declare function getApiClient(): ApiClient;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Generic authentication manager
3
+ * Handles token storage and retrieval
4
+ */
5
+ export declare class AuthManager {
6
+ /**
7
+ * Store authentication token
8
+ */
9
+ static setToken(token: string): void;
10
+ /**
11
+ * Get authentication token
12
+ */
13
+ static getToken(): string | null;
14
+ /**
15
+ * Remove authentication token
16
+ */
17
+ static clearToken(): void;
18
+ /**
19
+ * Store refresh token
20
+ */
21
+ static setRefreshToken(token: string): void;
22
+ /**
23
+ * Get refresh token
24
+ */
25
+ static getRefreshToken(): string | null;
26
+ /**
27
+ * Check if user is authenticated
28
+ */
29
+ static isAuthenticated(): boolean;
30
+ /**
31
+ * Get authorization header
32
+ */
33
+ static getAuthHeader(): Record<string, string>;
34
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * GraphClient - Backend Communication Layer
3
+ *
4
+ * Provides a type-safe interface to the qwanyx-brain SPU backend.
5
+ * All operations communicate through the unified `/spu/invoke` endpoint.
6
+ */
7
+ import type { GraphNode, GraphEdge, GraphClientConfig } from '../types';
8
+ export declare class GraphClient {
9
+ private config;
10
+ constructor(config: GraphClientConfig);
11
+ /**
12
+ * Call the Graph coprocessor
13
+ */
14
+ private callGraph;
15
+ /**
16
+ * Get auth token from localStorage (browser) or return empty string
17
+ */
18
+ private getToken;
19
+ /**
20
+ * Get children nodes
21
+ */
22
+ getChildren(parentId?: string): Promise<GraphNode[]>;
23
+ /**
24
+ * Get a specific node by ID
25
+ */
26
+ getNode(nodeId: string): Promise<GraphNode | null>;
27
+ /**
28
+ * Add a new node
29
+ */
30
+ addNode(node: Partial<GraphNode> & {
31
+ p?: string;
32
+ type: string;
33
+ }): Promise<GraphNode>;
34
+ /**
35
+ * Update an existing node
36
+ */
37
+ updateNode(nodeId: string, updates: Partial<GraphNode>): Promise<GraphNode>;
38
+ /**
39
+ * Delete a node
40
+ */
41
+ deleteNode(nodeId: string, cascade?: boolean): Promise<boolean>;
42
+ /**
43
+ * Get children with edges (supports different display modes)
44
+ */
45
+ getChildrenWithEdges(nodeId?: string, displayMode?: 'children' | 'edges' | 'both', edgeType?: string, nodeType?: string): Promise<GraphNode[]>;
46
+ /**
47
+ * Add an edge between two nodes
48
+ */
49
+ addEdge(sourceId: string | null, targetId: string, edgeType?: string, data?: Record<string, any>): Promise<{
50
+ success: boolean;
51
+ }>;
52
+ /**
53
+ * Delete an edge
54
+ */
55
+ deleteEdge(sourceId: string | null, targetId: string, edgeType?: string): Promise<{
56
+ deleted: boolean;
57
+ count: number;
58
+ }>;
59
+ /**
60
+ * Get edges from a source node
61
+ * @param sourceId - Source node ID (null for edges without source)
62
+ * @param edgeType - Optional edge type filter
63
+ * @param targetId - Optional target node ID for reverse lookups
64
+ */
65
+ getEdges(sourceId: string | null, edgeType?: string, targetId?: string): Promise<GraphEdge[]>;
66
+ /**
67
+ * Get ancestors of a node (path from root to node)
68
+ */
69
+ getAncestors(nodeId: string): Promise<GraphNode[]>;
70
+ /**
71
+ * Get tree structure starting from a root
72
+ */
73
+ getTree(rootId?: string, maxDepth?: number): Promise<any>;
74
+ /**
75
+ * Move a node to a new parent
76
+ */
77
+ moveNode(nodeId: string, newParentId?: string): Promise<GraphNode>;
78
+ /**
79
+ * Search nodes by query
80
+ */
81
+ searchNodes(query: string, type?: string): Promise<GraphNode[]>;
82
+ /**
83
+ * Get all nodes of a specific type
84
+ */
85
+ getNodesByType(type: string): Promise<GraphNode[]>;
86
+ /**
87
+ * Options for file upload
88
+ */
89
+ private defaultUploadOptions;
90
+ /**
91
+ * Convert File to base64 string
92
+ */
93
+ private fileToBase64;
94
+ /**
95
+ * Resize an image file if it exceeds maxDimension
96
+ * Returns the original file if not an image or no resize needed
97
+ */
98
+ private resizeImage;
99
+ /**
100
+ * Upload a file to a node
101
+ * @param nodeId - The node to attach the file to
102
+ * @param filename - The filename to use
103
+ * @param file - The File object to upload
104
+ * @param options - Upload options (maxSizeMB, maxImageDimension, imageQuality)
105
+ */
106
+ uploadFile(nodeId: string, filename: string, file: File, options?: {
107
+ maxSizeMB?: number;
108
+ maxImageDimension?: number;
109
+ imageQuality?: number;
110
+ }): Promise<{
111
+ success: boolean;
112
+ path?: string;
113
+ error?: string;
114
+ }>;
115
+ /**
116
+ * List files attached to a node
117
+ * @param nodeId - The node to list files for
118
+ */
119
+ listFiles(nodeId: string): Promise<{
120
+ filename: string;
121
+ path: string;
122
+ }[]>;
123
+ /**
124
+ * Delete a file from a node
125
+ * @param nodeId - The node the file belongs to
126
+ * @param filename - The filename to delete
127
+ */
128
+ deleteFile(nodeId: string, filename: string): Promise<{
129
+ success: boolean;
130
+ }>;
131
+ /**
132
+ * Get the URL for a file
133
+ * @param nodeId - The node the file belongs to
134
+ * @param filename - The filename
135
+ */
136
+ getFileUrl(nodeId: string, filename: string): string;
137
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * MailClient - Email Communication Layer
3
+ *
4
+ * Provides a type-safe interface to the mail coprocessor in qwanyx-brain.
5
+ * Handles email settings (with encrypted passwords) and IMAP operations.
6
+ */
7
+ import type { MailClientConfig, MailAccount, MailListResult, ImapResponse, FolderInfo } from '../types';
8
+ export declare class MailClient {
9
+ private config;
10
+ constructor(config: MailClientConfig);
11
+ /**
12
+ * Call a coprocessor (default: mail)
13
+ */
14
+ private callCoprocessor;
15
+ /**
16
+ * Call the Mail coprocessor (IMAP operations)
17
+ */
18
+ private callMail;
19
+ /**
20
+ * Call the Email coprocessor (SMTP operations)
21
+ */
22
+ private callEmail;
23
+ /**
24
+ * Get auth token from localStorage (browser) or return empty string
25
+ */
26
+ private getToken;
27
+ /**
28
+ * Get email settings with decrypted passwords
29
+ */
30
+ getSettings(): Promise<{
31
+ accounts: MailAccount[];
32
+ }>;
33
+ /**
34
+ * Save email settings (passwords encrypted server-side)
35
+ */
36
+ saveSettings(accounts: MailAccount[]): Promise<void>;
37
+ /**
38
+ * List emails from IMAP folder
39
+ * @param accountId - Account to use (defaults to first account)
40
+ * @param limit - Max emails to fetch
41
+ * @param folder - IMAP folder (default: INBOX). Gmail categories: CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
42
+ */
43
+ listEmails(accountId?: string, limit?: number, folder?: string): Promise<MailListResult>;
44
+ /**
45
+ * Delete emails by UID
46
+ */
47
+ deleteEmails(accountId: string, uids: number[], expunge?: boolean): Promise<{
48
+ success: boolean;
49
+ deleted: number;
50
+ }>;
51
+ /**
52
+ * Execute raw IMAP commands - thin proxy for stack-side logic
53
+ * Commands are strings like: "SELECT INBOX", "UID STORE 123 +FLAGS (\\Deleted)", "EXPUNGE"
54
+ */
55
+ imapExec(accountId: string, commands: string[]): Promise<{
56
+ success: boolean;
57
+ responses: ImapResponse[];
58
+ }>;
59
+ /**
60
+ * Move emails to trash (soft delete)
61
+ * Tries multiple folder names for Gmail locales
62
+ */
63
+ trashEmails(accountId: string, uids: number[]): Promise<{
64
+ success: boolean;
65
+ moved: number;
66
+ }>;
67
+ /**
68
+ * Archive emails (remove from inbox, keep in All Mail)
69
+ */
70
+ archiveEmails(accountId: string, uids: number[]): Promise<{
71
+ success: boolean;
72
+ archived: number;
73
+ }>;
74
+ /**
75
+ * List available folders
76
+ */
77
+ listFolders(accountId: string): Promise<{
78
+ success: boolean;
79
+ folders: FolderInfo[];
80
+ }>;
81
+ /**
82
+ * Get a single email by UID with full body content
83
+ */
84
+ getEmail(accountId: string, uid: number): Promise<{
85
+ uid: number;
86
+ from: string;
87
+ subject: string;
88
+ date: string;
89
+ body: string;
90
+ seen: boolean;
91
+ } | null>;
92
+ /**
93
+ * Send an email via SMTP
94
+ * Uses the email coprocessor which handles SMTP configuration
95
+ */
96
+ sendMail(options: {
97
+ to: string | string[];
98
+ subject: string;
99
+ body: string;
100
+ html?: string;
101
+ from?: string;
102
+ smtpConfig?: {
103
+ host: string;
104
+ port: number;
105
+ username: string;
106
+ password: string;
107
+ };
108
+ }): Promise<{
109
+ sent: boolean;
110
+ message_id?: string;
111
+ timestamp?: string;
112
+ error?: string;
113
+ }>;
114
+ }
@@ -0,0 +1,19 @@
1
+ export interface AnimatedCardFlipNode {
2
+ _id: string;
3
+ type: string;
4
+ title: string;
5
+ data: {
6
+ name: string;
7
+ image: string;
8
+ };
9
+ }
10
+ export interface AnimatedCardFlipProps {
11
+ nodes: AnimatedCardFlipNode[];
12
+ cardCount?: number;
13
+ minInterval?: number;
14
+ maxInterval?: number;
15
+ onCardClick?: (node: AnimatedCardFlipNode) => void;
16
+ cardSize?: 'small' | 'medium' | 'large';
17
+ className?: string;
18
+ }
19
+ export declare function AnimatedCardFlip({ nodes, cardCount, minInterval, maxInterval, onCardClick, cardSize, className }: AnimatedCardFlipProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Default Card Component for Stack list items
3
+ * Generic design that works with any data type
4
+ */
5
+ export interface CardProps<T = any> {
6
+ item: T;
7
+ onClick?: () => void;
8
+ title?: (item: T) => string;
9
+ subtitle?: (item: T) => string;
10
+ image?: (item: T) => string | undefined;
11
+ badge?: (item: T) => string | undefined;
12
+ }
13
+ export declare function Card<T = any>({ item, onClick, title, subtitle, image, badge, }: CardProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Default Detail View Component
3
+ * Generic detail view for any item
4
+ */
5
+ export interface DetailProps<T = any> {
6
+ item: T | null;
7
+ onClose?: () => void;
8
+ title?: (item: T) => string;
9
+ image?: (item: T) => string | undefined;
10
+ fields?: Array<{
11
+ label: string;
12
+ value: (item: T) => any;
13
+ }>;
14
+ }
15
+ export declare function Detail<T = any>({ item, onClose, title, image, fields, }: DetailProps<T>): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Mail Component
3
+ * Smart email list with selection, actions, and detail view
4
+ */
5
+ import React from 'react';
6
+ export interface EmailMessage {
7
+ uid: number;
8
+ subject: string;
9
+ from: string;
10
+ date: string;
11
+ seen: boolean;
12
+ }
13
+ export interface MailProps {
14
+ baseUrl: string;
15
+ systemId: string;
16
+ accountId: string;
17
+ limit?: number;
18
+ folder?: string;
19
+ selectable?: boolean;
20
+ showDetail?: boolean;
21
+ emptyMessage?: string;
22
+ autoLoad?: boolean;
23
+ onSelect?: (email: EmailMessage) => void;
24
+ onSelectionChange?: (uids: number[]) => void;
25
+ onDelete?: (uids: number[]) => void;
26
+ onError?: (error: Error) => void;
27
+ onLoad?: (emails: EmailMessage[]) => void;
28
+ renderItem?: (email: EmailMessage, selected: boolean) => React.ReactNode;
29
+ renderDetail?: (email: EmailMessage) => React.ReactNode;
30
+ renderActions?: (selectedUids: number[], actions: MailActions) => React.ReactNode;
31
+ renderEmpty?: () => React.ReactNode;
32
+ renderLoading?: () => React.ReactNode;
33
+ theme?: MailTheme;
34
+ }
35
+ export interface MailTheme {
36
+ background?: string;
37
+ cardBackground?: string;
38
+ selectedBackground?: string;
39
+ unreadBackground?: string;
40
+ text?: string;
41
+ textSecondary?: string;
42
+ border?: string;
43
+ primary?: string;
44
+ danger?: string;
45
+ }
46
+ export interface MailActions {
47
+ delete: () => Promise<void>;
48
+ archive: () => Promise<void>;
49
+ refresh: () => Promise<void>;
50
+ selectAll: () => void;
51
+ clearSelection: () => void;
52
+ }
53
+ export declare function Mail({ baseUrl, systemId, accountId, limit, folder, selectable, showDetail, emptyMessage, autoLoad, onSelect, onSelectionChange, onDelete, onError, onLoad, renderItem, renderDetail, renderActions, renderEmpty, renderLoading, theme: themeProp, }: MailProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Stack Component
3
+ * Apple/Superhuman inspired clean design
4
+ */
5
+ import React from 'react';
6
+ import type { QueryParams } from '../types';
7
+ export interface StackProps<T = any> {
8
+ endpoint: string;
9
+ params?: QueryParams;
10
+ layout?: 'list' | 'grid' | 'masonry';
11
+ title?: string;
12
+ emptyMessage?: string;
13
+ renderItem?: (item: T, index: number) => React.ReactNode;
14
+ keyExtractor?: (item: T, index: number) => string;
15
+ searchable?: boolean;
16
+ searchFields?: (keyof T)[];
17
+ searchPlaceholder?: string;
18
+ filters?: Array<{
19
+ field: keyof T;
20
+ label: string;
21
+ options?: Array<{
22
+ value: any;
23
+ label: string;
24
+ }>;
25
+ }>;
26
+ pageSize?: number;
27
+ onItemClick?: (item: T) => void;
28
+ onRefresh?: () => void;
29
+ theme?: {
30
+ background?: string;
31
+ cardBackground?: string;
32
+ text?: string;
33
+ textSecondary?: string;
34
+ border?: string;
35
+ primary?: string;
36
+ };
37
+ }
38
+ export declare function Stack<T = any>({ endpoint, params, layout, title, emptyMessage, renderItem, keyExtractor, searchable, searchFields, searchPlaceholder, filters, pageSize, onItemClick, onRefresh, theme, }: StackProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import type { HttpMethod } from '../types';
2
+ export interface UseMutationOptions<TData, TVariables> {
3
+ onSuccess?: (data: TData, variables: TVariables) => void;
4
+ onError?: (error: Error, variables: TVariables) => void;
5
+ }
6
+ export interface UseMutationResult<TData, TVariables> {
7
+ data: TData | null;
8
+ loading: boolean;
9
+ error: Error | null;
10
+ mutate: (variables: TVariables) => Promise<TData | null>;
11
+ reset: () => void;
12
+ }
13
+ /**
14
+ * Generic hook for mutations (POST, PUT, PATCH, DELETE)
15
+ */
16
+ export declare function useMutation<TData = any, TVariables = any>(endpoint: string, method?: HttpMethod, options?: UseMutationOptions<TData, TVariables>): UseMutationResult<TData, TVariables>;
@@ -0,0 +1,18 @@
1
+ import type { QueryParams } from '../types';
2
+ export interface UseQueryOptions<T> {
3
+ enabled?: boolean;
4
+ refetchOnMount?: boolean;
5
+ onSuccess?: (data: T) => void;
6
+ onError?: (error: Error) => void;
7
+ }
8
+ export interface UseQueryResult<T> {
9
+ data: T | null;
10
+ loading: boolean;
11
+ error: Error | null;
12
+ refetch: () => Promise<void>;
13
+ }
14
+ /**
15
+ * Generic hook for fetching data
16
+ * Similar to React Query but simpler
17
+ */
18
+ export declare function useQuery<T = any>(endpoint: string, params?: QueryParams, options?: UseQueryOptions<T>): UseQueryResult<T>;