lemma-sdk 0.2.34 → 0.2.36

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 (68) hide show
  1. package/README.md +112 -114
  2. package/dist/browser/lemma-client.js +176 -14
  3. package/dist/namespaces/integrations.d.ts +10 -2
  4. package/dist/namespaces/integrations.js +17 -2
  5. package/dist/openapi_client/index.d.ts +10 -2
  6. package/dist/openapi_client/index.js +1 -0
  7. package/dist/openapi_client/models/DatastoreDataType.d.ts +2 -0
  8. package/dist/openapi_client/models/DatastoreDataType.js +2 -0
  9. package/dist/openapi_client/models/FeedbackCategory.d.ts +7 -0
  10. package/dist/openapi_client/models/FeedbackCategory.js +12 -0
  11. package/dist/openapi_client/models/FlowRunEntity.d.ts +1 -0
  12. package/dist/openapi_client/models/IntegrationHelperAgentRequest.d.ts +13 -0
  13. package/dist/openapi_client/models/IntegrationHelperAgentResponse.d.ts +25 -0
  14. package/dist/openapi_client/models/OperationDetail.d.ts +3 -0
  15. package/dist/openapi_client/models/OperationDetailsBatchRequest.d.ts +9 -0
  16. package/dist/openapi_client/models/OperationDetailsBatchRequest.js +1 -0
  17. package/dist/openapi_client/models/OperationDetailsBatchResponse.d.ts +18 -0
  18. package/dist/openapi_client/models/OperationDetailsBatchResponse.js +1 -0
  19. package/dist/openapi_client/models/OperationDiscoverResponse.d.ts +26 -0
  20. package/dist/openapi_client/models/OperationDiscoverResponse.js +1 -0
  21. package/dist/openapi_client/models/OperationSummary.d.ts +3 -0
  22. package/dist/openapi_client/models/OrganizationCreateRequest.d.ts +2 -0
  23. package/dist/openapi_client/models/OrganizationInvitationRequest.d.ts +1 -0
  24. package/dist/openapi_client/models/OrganizationInvitationResponse.d.ts +3 -0
  25. package/dist/openapi_client/models/OrganizationMessageResponse.d.ts +1 -0
  26. package/dist/openapi_client/models/OrganizationResponse.d.ts +2 -0
  27. package/dist/openapi_client/models/OrganizationSlugAvailabilityResponse.d.ts +7 -0
  28. package/dist/openapi_client/models/OrganizationSlugAvailabilityResponse.js +1 -0
  29. package/dist/openapi_client/models/ReportFeedbackRequest.d.ts +30 -0
  30. package/dist/openapi_client/models/ReportFeedbackRequest.js +1 -0
  31. package/dist/openapi_client/models/ReportFeedbackResponse.d.ts +29 -0
  32. package/dist/openapi_client/models/ReportFeedbackResponse.js +1 -0
  33. package/dist/openapi_client/models/WorkflowInstallListResponse.d.ts +4 -0
  34. package/dist/openapi_client/models/WorkflowInstallListResponse.js +1 -0
  35. package/dist/openapi_client/services/AgentToolsService.d.ts +20 -0
  36. package/dist/openapi_client/services/AgentToolsService.js +36 -0
  37. package/dist/openapi_client/services/ApplicationsService.d.ts +10 -9
  38. package/dist/openapi_client/services/ApplicationsService.js +11 -10
  39. package/dist/openapi_client/services/IntegrationsService.d.ts +3 -2
  40. package/dist/openapi_client/services/IntegrationsService.js +4 -2
  41. package/dist/openapi_client/services/OrganizationsService.d.ts +18 -0
  42. package/dist/openapi_client/services/OrganizationsService.js +40 -0
  43. package/dist/openapi_client/services/WorkflowsService.d.ts +10 -0
  44. package/dist/openapi_client/services/WorkflowsService.js +21 -0
  45. package/dist/react/index.d.ts +14 -0
  46. package/dist/react/index.js +7 -0
  47. package/dist/react/sql-utils.d.ts +8 -0
  48. package/dist/react/sql-utils.js +62 -0
  49. package/dist/react/useCreateFolder.d.ts +22 -0
  50. package/dist/react/useCreateFolder.js +47 -0
  51. package/dist/react/useDatastoreQuery.d.ts +22 -0
  52. package/dist/react/useDatastoreQuery.js +67 -0
  53. package/dist/react/useDeleteFile.d.ts +19 -0
  54. package/dist/react/useDeleteFile.js +51 -0
  55. package/dist/react/useGlobalSearch.d.ts +62 -0
  56. package/dist/react/useGlobalSearch.js +170 -0
  57. package/dist/react/useRecordAggregates.d.ts +35 -0
  58. package/dist/react/useRecordAggregates.js +126 -0
  59. package/dist/react/useTaskSession.js +3 -2
  60. package/dist/react/useUpdateFile.d.ts +29 -0
  61. package/dist/react/useUpdateFile.js +51 -0
  62. package/dist/react/useUploadFile.d.ts +24 -0
  63. package/dist/react/useUploadFile.js +46 -0
  64. package/package.json +1 -1
  65. package/dist/openapi_client/models/AppDescriptorResponse.d.ts +0 -5
  66. package/dist/openapi_client/models/OperationListResponse.d.ts +0 -6
  67. /package/dist/openapi_client/models/{AppDescriptorResponse.js → IntegrationHelperAgentRequest.js} +0 -0
  68. /package/dist/openapi_client/models/{OperationListResponse.js → IntegrationHelperAgentResponse.js} +0 -0
@@ -52,8 +52,9 @@ export declare class IntegrationsService {
52
52
  * OAuth Callback
53
53
  * Handle OAuth callback and complete account connection. This endpoint is public and uses state parameter for security.
54
54
  * @param error
55
- * @returns AccountResponseSchema Successful Response
55
+ * @param format
56
+ * @returns string Successful Response
56
57
  * @throws ApiError
57
58
  */
58
- static integrationOauthCallback(error?: (string | null)): CancelablePromise<AccountResponseSchema>;
59
+ static integrationOauthCallback(error?: (string | null), format?: (string | null)): CancelablePromise<string>;
59
60
  }
@@ -103,15 +103,17 @@ export class IntegrationsService {
103
103
  * OAuth Callback
104
104
  * Handle OAuth callback and complete account connection. This endpoint is public and uses state parameter for security.
105
105
  * @param error
106
- * @returns AccountResponseSchema Successful Response
106
+ * @param format
107
+ * @returns string Successful Response
107
108
  * @throws ApiError
108
109
  */
109
- static integrationOauthCallback(error) {
110
+ static integrationOauthCallback(error, format) {
110
111
  return __request(OpenAPI, {
111
112
  method: 'GET',
112
113
  url: '/integrations/connect-requests/oauth/callback',
113
114
  query: {
114
115
  'error': error,
116
+ 'format': format,
115
117
  },
116
118
  errors: {
117
119
  422: `Validation Error`,
@@ -8,6 +8,7 @@ import type { OrganizationMemberListResponse } from '../models/OrganizationMembe
8
8
  import type { OrganizationMemberResponse } from '../models/OrganizationMemberResponse.js';
9
9
  import type { OrganizationMessageResponse } from '../models/OrganizationMessageResponse.js';
10
10
  import type { OrganizationResponse } from '../models/OrganizationResponse.js';
11
+ import type { OrganizationSlugAvailabilityResponse } from '../models/OrganizationSlugAvailabilityResponse.js';
11
12
  import type { UpdateMemberRoleRequest } from '../models/UpdateMemberRoleRequest.js';
12
13
  import type { CancelablePromise } from '../core/CancelablePromise.js';
13
14
  export declare class OrganizationsService {
@@ -62,6 +63,23 @@ export declare class OrganizationsService {
62
63
  * @throws ApiError
63
64
  */
64
65
  static orgInvitationAccept(invitationId: string): CancelablePromise<OrganizationMessageResponse>;
66
+ /**
67
+ * Check Organization Slug Availability
68
+ * Check whether an organization slug is available
69
+ * @param slug
70
+ * @returns OrganizationSlugAvailabilityResponse Successful Response
71
+ * @throws ApiError
72
+ */
73
+ static orgSlugAvailability(slug: string): CancelablePromise<OrganizationSlugAvailabilityResponse>;
74
+ /**
75
+ * Get Suggested Organizations
76
+ * Get auto-join organizations matching the current user's email domain
77
+ * @param limit
78
+ * @param pageToken
79
+ * @returns OrganizationListResponse Successful Response
80
+ * @throws ApiError
81
+ */
82
+ static orgSuggested(limit?: number, pageToken?: (string | null)): CancelablePromise<OrganizationListResponse>;
65
83
  /**
66
84
  * Get Organization
67
85
  * Get organization details
@@ -121,6 +121,46 @@ export class OrganizationsService {
121
121
  },
122
122
  });
123
123
  }
124
+ /**
125
+ * Check Organization Slug Availability
126
+ * Check whether an organization slug is available
127
+ * @param slug
128
+ * @returns OrganizationSlugAvailabilityResponse Successful Response
129
+ * @throws ApiError
130
+ */
131
+ static orgSlugAvailability(slug) {
132
+ return __request(OpenAPI, {
133
+ method: 'GET',
134
+ url: '/organizations/slug-availability',
135
+ query: {
136
+ 'slug': slug,
137
+ },
138
+ errors: {
139
+ 422: `Validation Error`,
140
+ },
141
+ });
142
+ }
143
+ /**
144
+ * Get Suggested Organizations
145
+ * Get auto-join organizations matching the current user's email domain
146
+ * @param limit
147
+ * @param pageToken
148
+ * @returns OrganizationListResponse Successful Response
149
+ * @throws ApiError
150
+ */
151
+ static orgSuggested(limit = 100, pageToken) {
152
+ return __request(OpenAPI, {
153
+ method: 'GET',
154
+ url: '/organizations/suggested',
155
+ query: {
156
+ 'limit': limit,
157
+ 'page_token': pageToken,
158
+ },
159
+ errors: {
160
+ 422: `Validation Error`,
161
+ },
162
+ });
163
+ }
124
164
  /**
125
165
  * Get Organization
126
166
  * Get organization details
@@ -3,6 +3,7 @@ import type { FlowResponse } from '../models/FlowResponse.js';
3
3
  import type { FlowRunEntity } from '../models/FlowRunEntity.js';
4
4
  import type { WorkflowCreateRequest } from '../models/WorkflowCreateRequest.js';
5
5
  import type { WorkflowGraphUpdateRequest } from '../models/WorkflowGraphUpdateRequest.js';
6
+ import type { WorkflowInstallListResponse } from '../models/WorkflowInstallListResponse.js';
6
7
  import type { WorkflowInstallRequest } from '../models/WorkflowInstallRequest.js';
7
8
  import type { WorkflowListResponse } from '../models/WorkflowListResponse.js';
8
9
  import type { WorkflowRunListResponse } from '../models/WorkflowRunListResponse.js';
@@ -115,6 +116,15 @@ export declare class WorkflowsService {
115
116
  * @throws ApiError
116
117
  */
117
118
  static workflowInstallCreate(podId: string, workflowName: string, requestBody: WorkflowInstallRequest): CancelablePromise<FlowInstallResponse>;
119
+ /**
120
+ * List Workflow Installs
121
+ * List the current user's installations for a workflow.
122
+ * @param podId
123
+ * @param workflowName
124
+ * @returns WorkflowInstallListResponse Successful Response
125
+ * @throws ApiError
126
+ */
127
+ static workflowInstallList(podId: string, workflowName: string): CancelablePromise<WorkflowInstallListResponse>;
118
128
  /**
119
129
  * Uninstall Workflow
120
130
  * Remove a previously created workflow installation binding.
@@ -255,6 +255,27 @@ export class WorkflowsService {
255
255
  },
256
256
  });
257
257
  }
258
+ /**
259
+ * List Workflow Installs
260
+ * List the current user's installations for a workflow.
261
+ * @param podId
262
+ * @param workflowName
263
+ * @returns WorkflowInstallListResponse Successful Response
264
+ * @throws ApiError
265
+ */
266
+ static workflowInstallList(podId, workflowName) {
267
+ return __request(OpenAPI, {
268
+ method: 'GET',
269
+ url: '/pods/{pod_id}/workflows/{workflow_name}/installs',
270
+ path: {
271
+ 'pod_id': podId,
272
+ 'workflow_name': workflowName,
273
+ },
274
+ errors: {
275
+ 422: `Validation Error`,
276
+ },
277
+ });
278
+ }
258
279
  /**
259
280
  * Uninstall Workflow
260
281
  * Remove a previously created workflow installation binding.
@@ -38,18 +38,32 @@ export { useFiles } from "./useFiles.js";
38
38
  export type { UseFilesOptions, UseFilesResult } from "./useFiles.js";
39
39
  export { useFile } from "./useFile.js";
40
40
  export type { UseFileOptions, UseFileResult } from "./useFile.js";
41
+ export { useDatastoreQuery } from "./useDatastoreQuery.js";
42
+ export type { UseDatastoreQueryOptions, UseDatastoreQueryResult, } from "./useDatastoreQuery.js";
43
+ export { useUploadFile } from "./useUploadFile.js";
44
+ export type { UploadFileInput, UseUploadFileOptions, UseUploadFileResult, } from "./useUploadFile.js";
45
+ export { useUpdateFile } from "./useUpdateFile.js";
46
+ export type { UpdateFileInput, UseUpdateFileOptions, UseUpdateFileResult, } from "./useUpdateFile.js";
47
+ export { useDeleteFile } from "./useDeleteFile.js";
48
+ export type { UseDeleteFileOptions, UseDeleteFileResult } from "./useDeleteFile.js";
49
+ export { useCreateFolder } from "./useCreateFolder.js";
50
+ export type { CreateFolderInput, UseCreateFolderOptions, UseCreateFolderResult, } from "./useCreateFolder.js";
41
51
  export { useFileSearch } from "./useFileSearch.js";
42
52
  export type { UseFileSearchOptions, UseFileSearchResult } from "./useFileSearch.js";
43
53
  export { useFileTree } from "./useFileTree.js";
44
54
  export type { UseFileTreeOptions, UseFileTreeResult } from "./useFileTree.js";
45
55
  export { useFilePreview } from "./useFilePreview.js";
46
56
  export type { FilePreviewMode, UseFilePreviewOptions, UseFilePreviewResult, } from "./useFilePreview.js";
57
+ export { useGlobalSearch } from "./useGlobalSearch.js";
58
+ export type { GlobalSearchFileResult, GlobalSearchFilesSource, GlobalSearchRecordResult, GlobalSearchResult, GlobalSearchTableSource, UseGlobalSearchOptions, UseGlobalSearchResult, } from "./useGlobalSearch.js";
47
59
  export { useTables } from "./useTables.js";
48
60
  export type { UseTablesOptions, UseTablesResult } from "./useTables.js";
49
61
  export { useTable } from "./useTable.js";
50
62
  export type { UseTableOptions, UseTableResult } from "./useTable.js";
51
63
  export { useRecords } from "./useRecords.js";
52
64
  export type { UseRecordsOptions, UseRecordsResult } from "./useRecords.js";
65
+ export { useRecordAggregates } from "./useRecordAggregates.js";
66
+ export type { RecordAggregateMetric, RecordAggregateOrderBy, UseRecordAggregatesOptions, UseRecordAggregatesResult, } from "./useRecordAggregates.js";
53
67
  export { useRecord } from "./useRecord.js";
54
68
  export type { UseRecordOptions, UseRecordResult } from "./useRecord.js";
55
69
  export { useCreateRecord } from "./useCreateRecord.js";
@@ -18,12 +18,19 @@ export { useCurrentUser } from "./useCurrentUser.js";
18
18
  export { usePodAccess } from "./usePodAccess.js";
19
19
  export { useFiles } from "./useFiles.js";
20
20
  export { useFile } from "./useFile.js";
21
+ export { useDatastoreQuery } from "./useDatastoreQuery.js";
22
+ export { useUploadFile } from "./useUploadFile.js";
23
+ export { useUpdateFile } from "./useUpdateFile.js";
24
+ export { useDeleteFile } from "./useDeleteFile.js";
25
+ export { useCreateFolder } from "./useCreateFolder.js";
21
26
  export { useFileSearch } from "./useFileSearch.js";
22
27
  export { useFileTree } from "./useFileTree.js";
23
28
  export { useFilePreview } from "./useFilePreview.js";
29
+ export { useGlobalSearch } from "./useGlobalSearch.js";
24
30
  export { useTables } from "./useTables.js";
25
31
  export { useTable } from "./useTable.js";
26
32
  export { useRecords } from "./useRecords.js";
33
+ export { useRecordAggregates } from "./useRecordAggregates.js";
27
34
  export { useRecord } from "./useRecord.js";
28
35
  export { useCreateRecord } from "./useCreateRecord.js";
29
36
  export { useUpdateRecord } from "./useUpdateRecord.js";
@@ -0,0 +1,8 @@
1
+ import type { RecordFilter } from "../types.js";
2
+ export declare function quoteIdentifierPath(value: string): string;
3
+ export declare function isSimpleIdentifierPath(value: string): boolean;
4
+ export declare function renderIdentifierPath(value: string): string;
5
+ export declare function escapeSqlString(value: string): string;
6
+ export declare function encodeSqlValue(value: unknown): string;
7
+ export declare function renderRecordFilter(filter: RecordFilter): string;
8
+ export declare function renderRecordFilters(filters?: RecordFilter[]): string;
@@ -0,0 +1,62 @@
1
+ function quoteIdentifierPart(value) {
2
+ return `"${value.replace(/"/g, "\"\"")}"`;
3
+ }
4
+ export function quoteIdentifierPath(value) {
5
+ return value
6
+ .split(".")
7
+ .map((part) => (part === "*" ? part : quoteIdentifierPart(part)))
8
+ .join(".");
9
+ }
10
+ export function isSimpleIdentifierPath(value) {
11
+ return /^[A-Za-z_][A-Za-z0-9_$]*(\.(\*|[A-Za-z_][A-Za-z0-9_$]*))*$/.test(value);
12
+ }
13
+ export function renderIdentifierPath(value) {
14
+ return isSimpleIdentifierPath(value) ? quoteIdentifierPath(value) : value;
15
+ }
16
+ export function escapeSqlString(value) {
17
+ return value.replace(/'/g, "''");
18
+ }
19
+ export function encodeSqlValue(value) {
20
+ if (value === null || typeof value === "undefined")
21
+ return "NULL";
22
+ if (typeof value === "boolean")
23
+ return value ? "TRUE" : "FALSE";
24
+ if (typeof value === "number") {
25
+ if (!Number.isFinite(value)) {
26
+ throw new Error("SQL values must be finite numbers.");
27
+ }
28
+ return String(value);
29
+ }
30
+ if (typeof value === "bigint")
31
+ return String(value);
32
+ if (value instanceof Date)
33
+ return `'${escapeSqlString(value.toISOString())}'`;
34
+ if (Array.isArray(value)) {
35
+ return `(${value.map((entry) => encodeSqlValue(entry)).join(", ")})`;
36
+ }
37
+ if (typeof value === "object") {
38
+ return `'${escapeSqlString(JSON.stringify(value))}'`;
39
+ }
40
+ return `'${escapeSqlString(String(value))}'`;
41
+ }
42
+ export function renderRecordFilter(filter) {
43
+ const field = filter.field?.trim();
44
+ if (!field) {
45
+ throw new Error("Record filters require a field.");
46
+ }
47
+ const operator = filter.op.trim().toUpperCase();
48
+ const lhs = renderIdentifierPath(field);
49
+ const values = Array.isArray(filter.values) ? filter.values : undefined;
50
+ if ((operator === "IN" || operator === "NOT IN") && values) {
51
+ return `${lhs} ${operator} ${encodeSqlValue(values)}`;
52
+ }
53
+ if ((operator === "IS" || operator === "IS NOT") && typeof filter.value === "undefined") {
54
+ return `${lhs} ${operator} NULL`;
55
+ }
56
+ return `${lhs} ${operator} ${encodeSqlValue(filter.value)}`;
57
+ }
58
+ export function renderRecordFilters(filters) {
59
+ if (!filters?.length)
60
+ return "";
61
+ return filters.map((filter) => `(${renderRecordFilter(filter)})`).join(" AND ");
62
+ }
@@ -0,0 +1,22 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ import type { FileResponse } from "../types.js";
3
+ export interface CreateFolderInput {
4
+ directoryPath?: string;
5
+ parentId?: string;
6
+ description?: string;
7
+ }
8
+ export interface UseCreateFolderOptions {
9
+ client: LemmaClient;
10
+ podId?: string;
11
+ enabled?: boolean;
12
+ onSuccess?: (folder: FileResponse) => void;
13
+ onError?: (error: unknown) => void;
14
+ }
15
+ export interface UseCreateFolderResult<TFile extends FileResponse = FileResponse> {
16
+ createdFolder: TFile | null;
17
+ isSubmitting: boolean;
18
+ error: Error | null;
19
+ createFolder: (name: string, options?: CreateFolderInput) => Promise<TFile | null>;
20
+ reset: () => void;
21
+ }
22
+ export declare function useCreateFolder<TFile extends FileResponse = FileResponse>({ client, podId, enabled, onSuccess, onError, }: UseCreateFolderOptions): UseCreateFolderResult<TFile>;
@@ -0,0 +1,47 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { normalizeError, resolvePodClient } from "./utils.js";
3
+ export function useCreateFolder({ client, podId, enabled = true, onSuccess, onError, }) {
4
+ const [createdFolder, setCreatedFolder] = useState(null);
5
+ const [isSubmitting, setIsSubmitting] = useState(false);
6
+ const [error, setError] = useState(null);
7
+ const onSuccessRef = useRef(onSuccess);
8
+ const onErrorRef = useRef(onError);
9
+ useEffect(() => { onSuccessRef.current = onSuccess; }, [onSuccess]);
10
+ useEffect(() => { onErrorRef.current = onError; }, [onError]);
11
+ const createFolder = useCallback(async (name, options = {}) => {
12
+ const trimmedName = name.trim();
13
+ if (!enabled || trimmedName.length === 0) {
14
+ return null;
15
+ }
16
+ setIsSubmitting(true);
17
+ setError(null);
18
+ try {
19
+ const scopedClient = resolvePodClient(client, podId);
20
+ const nextFolder = await scopedClient.files.folder.create(trimmedName, options);
21
+ setCreatedFolder(nextFolder);
22
+ onSuccessRef.current?.(nextFolder);
23
+ return nextFolder;
24
+ }
25
+ catch (createError) {
26
+ const normalized = normalizeError(createError, "Failed to create folder.");
27
+ setError(normalized);
28
+ onErrorRef.current?.(createError);
29
+ return null;
30
+ }
31
+ finally {
32
+ setIsSubmitting(false);
33
+ }
34
+ }, [client, enabled, podId]);
35
+ const reset = useCallback(() => {
36
+ setCreatedFolder(null);
37
+ setError(null);
38
+ setIsSubmitting(false);
39
+ }, []);
40
+ return useMemo(() => ({
41
+ createdFolder,
42
+ isSubmitting,
43
+ error,
44
+ createFolder,
45
+ reset,
46
+ }), [createFolder, createdFolder, error, isSubmitting, reset]);
47
+ }
@@ -0,0 +1,22 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ import type { DatastoreQueryResponse } from "../types.js";
3
+ export interface UseDatastoreQueryOptions {
4
+ client: LemmaClient;
5
+ podId?: string;
6
+ query?: string | null;
7
+ enabled?: boolean;
8
+ autoLoad?: boolean;
9
+ }
10
+ export interface UseDatastoreQueryResult<TRow extends Record<string, unknown> = Record<string, unknown>> {
11
+ response: DatastoreQueryResponse | null;
12
+ items: TRow[];
13
+ total: number;
14
+ sql: string;
15
+ isLoading: boolean;
16
+ error: Error | null;
17
+ refresh: (overrides?: {
18
+ query?: string | null;
19
+ }) => Promise<TRow[]>;
20
+ reset: () => void;
21
+ }
22
+ export declare function useDatastoreQuery<TRow extends Record<string, unknown> = Record<string, unknown>>({ client, podId, query, enabled, autoLoad, }: UseDatastoreQueryOptions): UseDatastoreQueryResult<TRow>;
@@ -0,0 +1,67 @@
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { normalizeError, resolvePodClient } from "./utils.js";
3
+ export function useDatastoreQuery({ client, podId, query = null, enabled = true, autoLoad = true, }) {
4
+ const [response, setResponse] = useState(null);
5
+ const [sql, setSql] = useState("");
6
+ const [isLoading, setIsLoading] = useState(false);
7
+ const [error, setError] = useState(null);
8
+ const trimmedQuery = typeof query === "string" ? query.trim() : "";
9
+ const isEnabled = enabled && trimmedQuery.length > 0;
10
+ const reset = useCallback(() => {
11
+ setResponse(null);
12
+ setSql("");
13
+ setError(null);
14
+ setIsLoading(false);
15
+ }, []);
16
+ const refresh = useCallback(async (overrides = {}, signal) => {
17
+ const nextQuery = typeof overrides.query === "string"
18
+ ? overrides.query.trim()
19
+ : trimmedQuery;
20
+ if (!enabled || nextQuery.length === 0) {
21
+ reset();
22
+ return [];
23
+ }
24
+ setIsLoading(true);
25
+ setError(null);
26
+ setSql(nextQuery);
27
+ try {
28
+ const scopedClient = resolvePodClient(client, podId);
29
+ const nextResponse = await scopedClient.datastore.query(nextQuery);
30
+ if (signal?.aborted)
31
+ return [];
32
+ setResponse(nextResponse);
33
+ return (nextResponse.items ?? []);
34
+ }
35
+ catch (queryError) {
36
+ if (signal?.aborted)
37
+ return [];
38
+ setError(normalizeError(queryError, "Failed to execute datastore query."));
39
+ setResponse(null);
40
+ return [];
41
+ }
42
+ finally {
43
+ if (!signal?.aborted)
44
+ setIsLoading(false);
45
+ }
46
+ }, [client, enabled, podId, reset, trimmedQuery]);
47
+ useEffect(() => {
48
+ if (!isEnabled || !autoLoad) {
49
+ if (!isEnabled)
50
+ reset();
51
+ return;
52
+ }
53
+ const controller = new AbortController();
54
+ void refresh({}, controller.signal);
55
+ return () => controller.abort();
56
+ }, [autoLoad, isEnabled, refresh, reset]);
57
+ return useMemo(() => ({
58
+ response,
59
+ items: (response?.items ?? []),
60
+ total: response?.total ?? 0,
61
+ sql,
62
+ isLoading,
63
+ error,
64
+ refresh,
65
+ reset,
66
+ }), [error, isLoading, refresh, reset, response, sql]);
67
+ }
@@ -0,0 +1,19 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ export interface UseDeleteFileOptions {
3
+ client: LemmaClient;
4
+ podId?: string;
5
+ path?: string | null;
6
+ enabled?: boolean;
7
+ onSuccess?: (path: string) => void;
8
+ onError?: (error: unknown) => void;
9
+ }
10
+ export interface UseDeleteFileResult {
11
+ deletedPath: string | null;
12
+ isSubmitting: boolean;
13
+ error: Error | null;
14
+ remove: (overrides?: {
15
+ path?: string | null;
16
+ }) => Promise<boolean>;
17
+ reset: () => void;
18
+ }
19
+ export declare function useDeleteFile({ client, podId, path, enabled, onSuccess, onError, }: UseDeleteFileOptions): UseDeleteFileResult;
@@ -0,0 +1,51 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { normalizeError, resolvePodClient } from "./utils.js";
3
+ export function useDeleteFile({ client, podId, path = null, enabled = true, onSuccess, onError, }) {
4
+ const [deletedPath, setDeletedPath] = useState(null);
5
+ const [isSubmitting, setIsSubmitting] = useState(false);
6
+ const [error, setError] = useState(null);
7
+ const onSuccessRef = useRef(onSuccess);
8
+ const onErrorRef = useRef(onError);
9
+ useEffect(() => { onSuccessRef.current = onSuccess; }, [onSuccess]);
10
+ useEffect(() => { onErrorRef.current = onError; }, [onError]);
11
+ const trimmedPath = typeof path === "string" ? path.trim() : "";
12
+ const isEnabled = enabled && trimmedPath.length > 0;
13
+ const remove = useCallback(async (overrides = {}) => {
14
+ const nextPath = typeof overrides.path === "string"
15
+ ? overrides.path.trim()
16
+ : trimmedPath;
17
+ if (!isEnabled || nextPath.length === 0) {
18
+ return false;
19
+ }
20
+ setIsSubmitting(true);
21
+ setError(null);
22
+ try {
23
+ const scopedClient = resolvePodClient(client, podId);
24
+ await scopedClient.files.delete(nextPath);
25
+ setDeletedPath(nextPath);
26
+ onSuccessRef.current?.(nextPath);
27
+ return true;
28
+ }
29
+ catch (removeError) {
30
+ const normalized = normalizeError(removeError, "Failed to delete file.");
31
+ setError(normalized);
32
+ onErrorRef.current?.(removeError);
33
+ return false;
34
+ }
35
+ finally {
36
+ setIsSubmitting(false);
37
+ }
38
+ }, [client, isEnabled, podId, trimmedPath]);
39
+ const reset = useCallback(() => {
40
+ setDeletedPath(null);
41
+ setError(null);
42
+ setIsSubmitting(false);
43
+ }, []);
44
+ return useMemo(() => ({
45
+ deletedPath,
46
+ isSubmitting,
47
+ error,
48
+ remove,
49
+ reset,
50
+ }), [deletedPath, error, isSubmitting, remove, reset]);
51
+ }
@@ -0,0 +1,62 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ import type { FileSearchResultSchema, RecordFilter, SearchMethod } from "../types.js";
3
+ export interface GlobalSearchTableSource {
4
+ key?: string;
5
+ tableName: string;
6
+ label?: string;
7
+ searchFields: string[];
8
+ displayField?: string;
9
+ subtitleField?: string;
10
+ limit?: number;
11
+ filters?: RecordFilter[];
12
+ }
13
+ export interface GlobalSearchFilesSource {
14
+ enabled?: boolean;
15
+ label?: string;
16
+ limit?: number;
17
+ searchMethod?: SearchMethod;
18
+ }
19
+ export interface GlobalSearchRecordResult {
20
+ kind: "record";
21
+ sourceKey: string;
22
+ sourceLabel: string;
23
+ tableName: string;
24
+ id: string;
25
+ title: string;
26
+ subtitle: string | null;
27
+ record: Record<string, unknown>;
28
+ }
29
+ export interface GlobalSearchFileResult {
30
+ kind: "file";
31
+ sourceKey: string;
32
+ sourceLabel: string;
33
+ path: string;
34
+ title: string;
35
+ subtitle: string | null;
36
+ result: FileSearchResultSchema;
37
+ }
38
+ export type GlobalSearchResult = GlobalSearchRecordResult | GlobalSearchFileResult;
39
+ export interface UseGlobalSearchOptions {
40
+ client: LemmaClient;
41
+ podId?: string;
42
+ query?: string;
43
+ tables?: GlobalSearchTableSource[];
44
+ files?: GlobalSearchFilesSource | false;
45
+ enabled?: boolean;
46
+ autoLoad?: boolean;
47
+ minQueryLength?: number;
48
+ }
49
+ export interface UseGlobalSearchResult {
50
+ results: GlobalSearchResult[];
51
+ recordResults: GlobalSearchRecordResult[];
52
+ fileResults: GlobalSearchFileResult[];
53
+ totalResults: number;
54
+ sourceErrors: Record<string, Error>;
55
+ isLoading: boolean;
56
+ error: Error | null;
57
+ search: (overrides?: {
58
+ query?: string;
59
+ }) => Promise<GlobalSearchResult[]>;
60
+ reset: () => void;
61
+ }
62
+ export declare function useGlobalSearch({ client, podId, query, tables, files, enabled, autoLoad, minQueryLength, }: UseGlobalSearchOptions): UseGlobalSearchResult;