lemma-sdk 0.2.33 → 0.2.35

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 (170) hide show
  1. package/README.md +71 -98
  2. package/dist/browser/lemma-client.js +70 -15
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.js +2 -1
  5. package/dist/namespaces/pod-surfaces.js +1 -1
  6. package/dist/namespaces/workflows.d.ts +1 -1
  7. package/dist/openapi_client/index.d.ts +50 -12
  8. package/dist/openapi_client/index.js +10 -2
  9. package/dist/openapi_client/models/AdminConsentInfoResponse.d.ts +6 -0
  10. package/dist/openapi_client/models/AssistantSurfaceResponse.d.ts +16 -1
  11. package/dist/openapi_client/models/AssistantSurfaceStatus.d.ts +5 -0
  12. package/dist/openapi_client/models/AssistantSurfaceStatus.js +10 -0
  13. package/dist/openapi_client/models/ConversationMessageResponse.d.ts +4 -0
  14. package/dist/openapi_client/models/ConversationResponse.d.ts +3 -0
  15. package/dist/openapi_client/models/ConversationType.d.ts +8 -0
  16. package/dist/openapi_client/models/ConversationType.js +13 -0
  17. package/dist/openapi_client/models/CreateSurfaceRequest.d.ts +16 -5
  18. package/dist/openapi_client/models/{DataStoreFlowStart.d.ts → DataStoreFlowStartInput.d.ts} +1 -1
  19. package/dist/openapi_client/models/DataStoreFlowStartOutput.d.ts +11 -0
  20. package/dist/openapi_client/models/DataStoreWorkflowStartInput.d.ts +11 -0
  21. package/dist/openapi_client/models/DataStoreWorkflowStartOutput.d.ts +11 -0
  22. package/dist/openapi_client/models/DatastoreDataType.d.ts +2 -0
  23. package/dist/openapi_client/models/DatastoreDataType.js +2 -0
  24. package/dist/openapi_client/models/{EventFlowStart.d.ts → EventFlowStartInput.d.ts} +1 -1
  25. package/dist/openapi_client/models/EventFlowStartOutput.d.ts +19 -0
  26. package/dist/openapi_client/models/EventWorkflowStartInput.d.ts +11 -0
  27. package/dist/openapi_client/models/EventWorkflowStartOutput.d.ts +11 -0
  28. package/dist/openapi_client/models/FlowInstallResponse.d.ts +15 -0
  29. package/dist/openapi_client/models/FlowResponse.d.ts +5 -2
  30. package/dist/openapi_client/models/GmailSurfaceConfig.d.ts +7 -0
  31. package/dist/openapi_client/models/GmailSurfaceConfig.js +1 -0
  32. package/dist/openapi_client/models/GmailSurfaceConfigInput.d.ts +4 -0
  33. package/dist/openapi_client/models/GmailSurfaceConfigInput.js +1 -0
  34. package/dist/openapi_client/models/GrantPermissionRequest.d.ts +6 -0
  35. package/dist/openapi_client/models/GrantPermissionRequest.js +1 -0
  36. package/dist/openapi_client/models/ManualWorkflowStartInput.d.ts +10 -0
  37. package/dist/openapi_client/models/ManualWorkflowStartInput.js +1 -0
  38. package/dist/openapi_client/models/ManualWorkflowStartOutput.d.ts +10 -0
  39. package/dist/openapi_client/models/ManualWorkflowStartOutput.js +1 -0
  40. package/dist/openapi_client/models/OrganizationInvitationRequest.d.ts +2 -0
  41. package/dist/openapi_client/models/OrganizationInvitationResponse.d.ts +2 -0
  42. package/dist/openapi_client/models/OutlookSurfaceConfig.d.ts +7 -0
  43. package/dist/openapi_client/models/OutlookSurfaceConfig.js +1 -0
  44. package/dist/openapi_client/models/OutlookSurfaceConfigInput.d.ts +4 -0
  45. package/dist/openapi_client/models/OutlookSurfaceConfigInput.js +1 -0
  46. package/dist/openapi_client/models/ResourcePermissionListResponse.d.ts +4 -0
  47. package/dist/openapi_client/models/ResourcePermissionListResponse.js +1 -0
  48. package/dist/openapi_client/models/ResourcePermissionResponse.d.ts +12 -0
  49. package/dist/openapi_client/models/ResourcePermissionResponse.js +1 -0
  50. package/dist/openapi_client/models/{ScheduledFlowStart.d.ts → ScheduledFlowStartInput.d.ts} +1 -1
  51. package/dist/openapi_client/models/ScheduledFlowStartInput.js +1 -0
  52. package/dist/openapi_client/models/ScheduledFlowStartOutput.d.ts +7 -0
  53. package/dist/openapi_client/models/ScheduledFlowStartOutput.js +1 -0
  54. package/dist/openapi_client/models/ScheduledWorkflowStartInput.d.ts +11 -0
  55. package/dist/openapi_client/models/ScheduledWorkflowStartInput.js +1 -0
  56. package/dist/openapi_client/models/ScheduledWorkflowStartOutput.d.ts +11 -0
  57. package/dist/openapi_client/models/ScheduledWorkflowStartOutput.js +1 -0
  58. package/dist/openapi_client/models/SetVisibilityRequest.d.ts +3 -0
  59. package/dist/openapi_client/models/SetVisibilityRequest.js +1 -0
  60. package/dist/openapi_client/models/SlackCredentialsInput.d.ts +5 -0
  61. package/dist/openapi_client/models/SlackCredentialsInput.js +1 -0
  62. package/dist/openapi_client/models/SlackSurfaceConfig.d.ts +10 -0
  63. package/dist/openapi_client/models/SlackSurfaceConfig.js +1 -0
  64. package/dist/openapi_client/models/{SlackSurfaceConfigCreate.d.ts → SlackSurfaceConfigInput.d.ts} +1 -1
  65. package/dist/openapi_client/models/SlackSurfaceConfigInput.js +1 -0
  66. package/dist/openapi_client/models/SurfaceCredentialMode.d.ts +4 -0
  67. package/dist/openapi_client/models/SurfaceCredentialMode.js +9 -0
  68. package/dist/openapi_client/models/SurfaceIntegrationSetupGuide.d.ts +13 -0
  69. package/dist/openapi_client/models/SurfaceIntegrationSetupGuide.js +1 -0
  70. package/dist/openapi_client/models/SurfacePlatform.d.ts +8 -0
  71. package/dist/openapi_client/models/SurfacePlatform.js +13 -0
  72. package/dist/openapi_client/models/SurfacePlatformSetupGuideResponse.d.ts +9 -0
  73. package/dist/openapi_client/models/SurfacePlatformSetupGuideResponse.js +1 -0
  74. package/dist/openapi_client/models/SurfaceRoutingScope.d.ts +4 -0
  75. package/dist/openapi_client/models/SurfaceRoutingScope.js +9 -0
  76. package/dist/openapi_client/models/SurfaceSetupField.d.ts +10 -0
  77. package/dist/openapi_client/models/SurfaceSetupField.js +1 -0
  78. package/dist/openapi_client/models/SurfaceSetupFieldSource.d.ts +4 -0
  79. package/dist/openapi_client/models/SurfaceSetupFieldSource.js +9 -0
  80. package/dist/openapi_client/models/SurfaceSetupMode.d.ts +5 -0
  81. package/dist/openapi_client/models/SurfaceSetupMode.js +10 -0
  82. package/dist/openapi_client/models/SurfaceSetupPhase.d.ts +6 -0
  83. package/dist/openapi_client/models/SurfaceSetupPhase.js +11 -0
  84. package/dist/openapi_client/models/SurfaceSetupStep.d.ts +6 -0
  85. package/dist/openapi_client/models/SurfaceSetupStep.js +1 -0
  86. package/dist/openapi_client/models/SurfaceWebhookMode.d.ts +4 -0
  87. package/dist/openapi_client/models/SurfaceWebhookMode.js +9 -0
  88. package/dist/openapi_client/models/TeamsCredentialsInput.d.ts +6 -0
  89. package/dist/openapi_client/models/TeamsCredentialsInput.js +1 -0
  90. package/dist/openapi_client/models/TeamsSurfaceConfig.d.ts +9 -0
  91. package/dist/openapi_client/models/TeamsSurfaceConfig.js +1 -0
  92. package/dist/openapi_client/models/{TeamsSurfaceConfigCreate.d.ts → TeamsSurfaceConfigInput.d.ts} +1 -1
  93. package/dist/openapi_client/models/TeamsSurfaceConfigInput.js +1 -0
  94. package/dist/openapi_client/models/TelegramCredentialsInput.d.ts +5 -0
  95. package/dist/openapi_client/models/TelegramCredentialsInput.js +1 -0
  96. package/dist/openapi_client/models/TelegramSurfaceConfig.d.ts +6 -0
  97. package/dist/openapi_client/models/TelegramSurfaceConfig.js +1 -0
  98. package/dist/openapi_client/models/TelegramSurfaceConfigInput.d.ts +6 -0
  99. package/dist/openapi_client/models/TelegramSurfaceConfigInput.js +1 -0
  100. package/dist/openapi_client/models/UpdateSurfaceRequest.d.ts +17 -5
  101. package/dist/openapi_client/models/WhatsAppCredentialsInput.d.ts +8 -0
  102. package/dist/openapi_client/models/WhatsAppCredentialsInput.js +1 -0
  103. package/dist/openapi_client/models/WhatsAppSurfaceConfig.d.ts +6 -0
  104. package/dist/openapi_client/models/WhatsAppSurfaceConfig.js +1 -0
  105. package/dist/openapi_client/models/WhatsAppSurfaceConfigInput.d.ts +6 -0
  106. package/dist/openapi_client/models/WhatsAppSurfaceConfigInput.js +1 -0
  107. package/dist/openapi_client/models/WorkflowCreateRequest.d.ts +5 -2
  108. package/dist/openapi_client/models/WorkflowGraphUpdateRequest.d.ts +5 -2
  109. package/dist/openapi_client/models/WorkflowUpdateRequest.d.ts +5 -2
  110. package/dist/openapi_client/services/AssistantSurfacesIngressService.d.ts +51 -0
  111. package/dist/openapi_client/services/AssistantSurfacesIngressService.js +111 -0
  112. package/dist/openapi_client/services/AssistantSurfacesService.d.ts +27 -6
  113. package/dist/openapi_client/services/AssistantSurfacesService.js +62 -7
  114. package/dist/openapi_client/services/AuthorizationService.d.ts +47 -0
  115. package/dist/openapi_client/services/AuthorizationService.js +100 -0
  116. package/dist/openapi_client/services/DesksService.d.ts +4 -4
  117. package/dist/openapi_client/services/DesksService.js +6 -6
  118. package/dist/openapi_client/services/WorkflowsService.d.ts +3 -3
  119. package/dist/openapi_client/services/WorkflowsService.js +1 -1
  120. package/dist/react/index.d.ts +20 -0
  121. package/dist/react/index.js +10 -0
  122. package/dist/react/sql-utils.d.ts +8 -0
  123. package/dist/react/sql-utils.js +62 -0
  124. package/dist/react/useAddPodMember.d.ts +22 -0
  125. package/dist/react/useAddPodMember.js +51 -0
  126. package/dist/react/useCreateFolder.d.ts +22 -0
  127. package/dist/react/useCreateFolder.js +47 -0
  128. package/dist/react/useDatastoreQuery.d.ts +22 -0
  129. package/dist/react/useDatastoreQuery.js +67 -0
  130. package/dist/react/useDeleteFile.d.ts +19 -0
  131. package/dist/react/useDeleteFile.js +51 -0
  132. package/dist/react/useGlobalSearch.d.ts +62 -0
  133. package/dist/react/useGlobalSearch.js +170 -0
  134. package/dist/react/useRecordAggregates.d.ts +35 -0
  135. package/dist/react/useRecordAggregates.js +126 -0
  136. package/dist/react/useRemovePodMember.d.ts +19 -0
  137. package/dist/react/useRemovePodMember.js +50 -0
  138. package/dist/react/useTaskSession.js +3 -2
  139. package/dist/react/useUpdateFile.d.ts +29 -0
  140. package/dist/react/useUpdateFile.js +51 -0
  141. package/dist/react/useUpdatePodMemberRole.d.ts +20 -0
  142. package/dist/react/useUpdatePodMemberRole.js +50 -0
  143. package/dist/react/useUploadFile.d.ts +24 -0
  144. package/dist/react/useUploadFile.js +46 -0
  145. package/dist/react/useWorkflowStart.d.ts +2 -2
  146. package/dist/record-display.d.ts +20 -0
  147. package/dist/record-display.js +78 -0
  148. package/dist/record-form.d.ts +4 -0
  149. package/dist/record-form.js +16 -0
  150. package/dist/types.d.ts +2 -0
  151. package/package.json +1 -1
  152. package/dist/openapi_client/models/EmailSurfaceConfigCreate.d.ts +0 -5
  153. package/dist/openapi_client/models/FlowInstallEntity.d.ts +0 -16
  154. package/dist/openapi_client/models/FlowStartType.d.ts +0 -6
  155. package/dist/openapi_client/models/FlowStartType.js +0 -11
  156. package/dist/openapi_client/models/FlowStart_Input.d.ts +0 -14
  157. package/dist/openapi_client/models/FlowStart_Output.d.ts +0 -14
  158. package/dist/openapi_client/models/WhatsAppSurfaceConfigCreate.d.ts +0 -5
  159. package/dist/openapi_client/services/PublicDesksService.d.ts +0 -10
  160. package/dist/openapi_client/services/PublicDesksService.js +0 -22
  161. /package/dist/openapi_client/models/{DataStoreFlowStart.js → AdminConsentInfoResponse.js} +0 -0
  162. /package/dist/openapi_client/models/{EmailSurfaceConfigCreate.js → DataStoreFlowStartInput.js} +0 -0
  163. /package/dist/openapi_client/models/{EventFlowStart.js → DataStoreFlowStartOutput.js} +0 -0
  164. /package/dist/openapi_client/models/{FlowInstallEntity.js → DataStoreWorkflowStartInput.js} +0 -0
  165. /package/dist/openapi_client/models/{FlowStart_Input.js → DataStoreWorkflowStartOutput.js} +0 -0
  166. /package/dist/openapi_client/models/{FlowStart_Output.js → EventFlowStartInput.js} +0 -0
  167. /package/dist/openapi_client/models/{ScheduledFlowStart.js → EventFlowStartOutput.js} +0 -0
  168. /package/dist/openapi_client/models/{SlackSurfaceConfigCreate.js → EventWorkflowStartInput.js} +0 -0
  169. /package/dist/openapi_client/models/{TeamsSurfaceConfigCreate.js → EventWorkflowStartOutput.js} +0 -0
  170. /package/dist/openapi_client/models/{WhatsAppSurfaceConfigCreate.js → FlowInstallResponse.js} +0 -0
@@ -0,0 +1,126 @@
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { encodeSqlValue, quoteIdentifierPath, renderIdentifierPath, renderRecordFilters } from "./sql-utils.js";
3
+ import { normalizeError, resolvePodClient, stringifyComparable } from "./utils.js";
4
+ function buildMetricExpression(metric) {
5
+ const fn = metric.op.toUpperCase();
6
+ if (metric.op === "count" && !metric.field) {
7
+ return `${fn}(*) AS ${quoteIdentifierPath(metric.key)}`;
8
+ }
9
+ if (!metric.field) {
10
+ throw new Error(`Aggregate metric "${metric.key}" requires a field.`);
11
+ }
12
+ const renderedField = renderIdentifierPath(metric.field);
13
+ const distinct = metric.distinct ? "DISTINCT " : "";
14
+ return `${fn}(${distinct}${renderedField}) AS ${quoteIdentifierPath(metric.key)}`;
15
+ }
16
+ function buildRecordAggregatesQuery({ tableName, metrics, groupBy, filters, limit, offset, orderBy, }) {
17
+ const groups = (Array.isArray(groupBy) ? groupBy : groupBy ? [groupBy] : [])
18
+ .map((field) => field.trim())
19
+ .filter((field) => field.length > 0);
20
+ const selectParts = [
21
+ ...groups.map((field) => `${renderIdentifierPath(field)} AS ${quoteIdentifierPath(field)}`),
22
+ ...metrics.map((metric) => buildMetricExpression(metric)),
23
+ ];
24
+ const whereClause = renderRecordFilters(filters);
25
+ const orderClause = orderBy?.length
26
+ ? ` ORDER BY ${orderBy.map((entry) => `${renderIdentifierPath(entry.field)} ${(entry.direction ?? "desc").toUpperCase()}`).join(", ")}`
27
+ : "";
28
+ const groupClause = groups.length
29
+ ? ` GROUP BY ${groups.map((field) => renderIdentifierPath(field)).join(", ")}`
30
+ : "";
31
+ const limitClause = typeof limit === "number" ? ` LIMIT ${encodeSqlValue(limit)}` : "";
32
+ const offsetClause = typeof offset === "number" ? ` OFFSET ${encodeSqlValue(offset)}` : "";
33
+ return [
34
+ `SELECT ${selectParts.join(", ")}`,
35
+ `FROM ${quoteIdentifierPath(tableName)}`,
36
+ whereClause ? `WHERE ${whereClause}` : "",
37
+ groupClause,
38
+ orderClause,
39
+ limitClause,
40
+ offsetClause,
41
+ ].filter(Boolean).join(" ");
42
+ }
43
+ export function useRecordAggregates({ client, podId, tableName, metrics, groupBy, filters = [], limit, offset, orderBy, enabled = true, autoLoad = true, }) {
44
+ const [rows, setRows] = useState([]);
45
+ const [total, setTotal] = useState(0);
46
+ const [sql, setSql] = useState("");
47
+ const [isLoading, setIsLoading] = useState(false);
48
+ const [error, setError] = useState(null);
49
+ const metricsKey = stringifyComparable(metrics);
50
+ const filtersKey = stringifyComparable(filters);
51
+ const groupByKey = stringifyComparable(groupBy);
52
+ const orderByKey = stringifyComparable(orderBy);
53
+ const stableMetrics = useMemo(() => metrics, [metricsKey]);
54
+ const stableFilters = useMemo(() => filters, [filtersKey]);
55
+ const stableGroupBy = useMemo(() => groupBy, [groupByKey]);
56
+ const stableOrderBy = useMemo(() => orderBy, [orderByKey]);
57
+ const trimmedTableName = tableName.trim();
58
+ const isEnabled = enabled && trimmedTableName.length > 0 && stableMetrics.length > 0;
59
+ const refresh = useCallback(async (signal) => {
60
+ if (!isEnabled) {
61
+ setRows([]);
62
+ setTotal(0);
63
+ setSql("");
64
+ setError(null);
65
+ setIsLoading(false);
66
+ return [];
67
+ }
68
+ setIsLoading(true);
69
+ setError(null);
70
+ try {
71
+ const scopedClient = resolvePodClient(client, podId);
72
+ const nextSql = buildRecordAggregatesQuery({
73
+ tableName: trimmedTableName,
74
+ metrics: stableMetrics,
75
+ groupBy: stableGroupBy,
76
+ filters: stableFilters,
77
+ limit,
78
+ offset,
79
+ orderBy: stableOrderBy,
80
+ });
81
+ setSql(nextSql);
82
+ const response = await scopedClient.datastore.query(nextSql);
83
+ if (signal?.aborted)
84
+ return [];
85
+ const nextRows = (response.items ?? []);
86
+ setRows(nextRows);
87
+ setTotal(response.total ?? nextRows.length);
88
+ return nextRows;
89
+ }
90
+ catch (aggregateError) {
91
+ if (signal?.aborted)
92
+ return [];
93
+ const normalized = normalizeError(aggregateError, "Failed to load record aggregates.");
94
+ setError(normalized);
95
+ return [];
96
+ }
97
+ finally {
98
+ if (!signal?.aborted)
99
+ setIsLoading(false);
100
+ }
101
+ }, [client, isEnabled, limit, offset, podId, stableFilters, stableGroupBy, stableMetrics, stableOrderBy, trimmedTableName]);
102
+ useEffect(() => {
103
+ if (!isEnabled) {
104
+ setRows([]);
105
+ setTotal(0);
106
+ setSql("");
107
+ setError(null);
108
+ setIsLoading(false);
109
+ return;
110
+ }
111
+ if (!autoLoad)
112
+ return;
113
+ const controller = new AbortController();
114
+ void refresh(controller.signal);
115
+ return () => controller.abort();
116
+ }, [autoLoad, isEnabled, refresh]);
117
+ return useMemo(() => ({
118
+ rows,
119
+ row: rows[0] ?? null,
120
+ total,
121
+ sql,
122
+ isLoading,
123
+ error,
124
+ refresh,
125
+ }), [error, isLoading, refresh, rows, sql, total]);
126
+ }
@@ -0,0 +1,19 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ export interface UseRemovePodMemberOptions {
3
+ client: LemmaClient;
4
+ podId?: string;
5
+ memberId?: string | null;
6
+ enabled?: boolean;
7
+ onSuccess?: (memberId: string) => void;
8
+ onError?: (error: unknown) => void;
9
+ }
10
+ export interface UseRemovePodMemberResult {
11
+ removedMemberId: string | null;
12
+ isSubmitting: boolean;
13
+ error: Error | null;
14
+ remove: (overrides?: {
15
+ memberId?: string | null;
16
+ }) => Promise<boolean>;
17
+ reset: () => void;
18
+ }
19
+ export declare function useRemovePodMember({ client, podId, memberId, enabled, onSuccess, onError, }: UseRemovePodMemberOptions): UseRemovePodMemberResult;
@@ -0,0 +1,50 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { normalizeError, resolvePodId } from "./utils.js";
3
+ export function useRemovePodMember({ client, podId, memberId = null, enabled = true, onSuccess, onError, }) {
4
+ const [removedMemberId, setRemovedMemberId] = 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 trimmedMemberId = typeof memberId === "string" ? memberId.trim() : "";
12
+ const remove = useCallback(async (overrides = {}) => {
13
+ const nextMemberId = typeof overrides.memberId === "string"
14
+ ? overrides.memberId.trim()
15
+ : trimmedMemberId;
16
+ if (!enabled || nextMemberId.length === 0) {
17
+ return false;
18
+ }
19
+ setIsSubmitting(true);
20
+ setError(null);
21
+ try {
22
+ const resolvedPodId = resolvePodId(client, podId);
23
+ await client.podMembers.remove(resolvedPodId, nextMemberId);
24
+ setRemovedMemberId(nextMemberId);
25
+ onSuccessRef.current?.(nextMemberId);
26
+ return true;
27
+ }
28
+ catch (mutationError) {
29
+ const normalized = normalizeError(mutationError, "Failed to remove pod member.");
30
+ setError(normalized);
31
+ onErrorRef.current?.(mutationError);
32
+ return false;
33
+ }
34
+ finally {
35
+ setIsSubmitting(false);
36
+ }
37
+ }, [client, enabled, podId, trimmedMemberId]);
38
+ const reset = useCallback(() => {
39
+ setRemovedMemberId(null);
40
+ setError(null);
41
+ setIsSubmitting(false);
42
+ }, []);
43
+ return useMemo(() => ({
44
+ removedMemberId,
45
+ isSubmitting,
46
+ error,
47
+ remove,
48
+ reset,
49
+ }), [error, isSubmitting, remove, removedMemberId, reset]);
50
+ }
@@ -30,12 +30,13 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
30
30
  }
31
31
  }, []);
32
32
  const setTaskId = useCallback((nextTaskId) => {
33
- abortRef.current?.abort();
34
- abortRef.current = null;
35
33
  setTaskIdState((currentTaskId) => {
36
34
  if (currentTaskId === nextTaskId) {
37
35
  return currentTaskId;
38
36
  }
37
+ abortRef.current?.abort();
38
+ abortRef.current = null;
39
+ taskIdRef.current = nextTaskId;
39
40
  setError(null);
40
41
  setIsStreaming(false);
41
42
  if (!nextTaskId) {
@@ -0,0 +1,29 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ import type { FileResponse } from "../types.js";
3
+ export interface UpdateFileInput {
4
+ file?: Blob;
5
+ name?: string;
6
+ description?: string;
7
+ directoryPath?: string;
8
+ parentId?: string;
9
+ newPath?: string;
10
+ searchEnabled?: boolean;
11
+ }
12
+ export interface UseUpdateFileOptions {
13
+ client: LemmaClient;
14
+ podId?: string;
15
+ path?: string | null;
16
+ enabled?: boolean;
17
+ onSuccess?: (file: FileResponse) => void;
18
+ onError?: (error: unknown) => void;
19
+ }
20
+ export interface UseUpdateFileResult<TFile extends FileResponse = FileResponse> {
21
+ updatedFile: TFile | null;
22
+ isSubmitting: boolean;
23
+ error: Error | null;
24
+ update: (input?: UpdateFileInput, overrides?: {
25
+ path?: string | null;
26
+ }) => Promise<TFile | null>;
27
+ reset: () => void;
28
+ }
29
+ export declare function useUpdateFile<TFile extends FileResponse = FileResponse>({ client, podId, path, enabled, onSuccess, onError, }: UseUpdateFileOptions): UseUpdateFileResult<TFile>;
@@ -0,0 +1,51 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { normalizeError, resolvePodClient } from "./utils.js";
3
+ export function useUpdateFile({ client, podId, path = null, enabled = true, onSuccess, onError, }) {
4
+ const [updatedFile, setUpdatedFile] = 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 update = useCallback(async (input = {}, overrides = {}) => {
14
+ const nextPath = typeof overrides.path === "string"
15
+ ? overrides.path.trim()
16
+ : trimmedPath;
17
+ if (!isEnabled || nextPath.length === 0) {
18
+ return null;
19
+ }
20
+ setIsSubmitting(true);
21
+ setError(null);
22
+ try {
23
+ const scopedClient = resolvePodClient(client, podId);
24
+ const nextFile = await scopedClient.files.update(nextPath, input);
25
+ setUpdatedFile(nextFile);
26
+ onSuccessRef.current?.(nextFile);
27
+ return nextFile;
28
+ }
29
+ catch (updateError) {
30
+ const normalized = normalizeError(updateError, "Failed to update file.");
31
+ setError(normalized);
32
+ onErrorRef.current?.(updateError);
33
+ return null;
34
+ }
35
+ finally {
36
+ setIsSubmitting(false);
37
+ }
38
+ }, [client, isEnabled, podId, trimmedPath]);
39
+ const reset = useCallback(() => {
40
+ setUpdatedFile(null);
41
+ setError(null);
42
+ setIsSubmitting(false);
43
+ }, []);
44
+ return useMemo(() => ({
45
+ updatedFile,
46
+ isSubmitting,
47
+ error,
48
+ update,
49
+ reset,
50
+ }), [error, isSubmitting, reset, update, updatedFile]);
51
+ }
@@ -0,0 +1,20 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ import type { PodMember, PodRole } from "../types.js";
3
+ export interface UseUpdatePodMemberRoleOptions {
4
+ client: LemmaClient;
5
+ podId?: string;
6
+ memberId?: string | null;
7
+ enabled?: boolean;
8
+ onSuccess?: (member: PodMember) => void;
9
+ onError?: (error: unknown) => void;
10
+ }
11
+ export interface UseUpdatePodMemberRoleResult {
12
+ updatedMember: PodMember | null;
13
+ isSubmitting: boolean;
14
+ error: Error | null;
15
+ updateRole: (role: PodRole, overrides?: {
16
+ memberId?: string | null;
17
+ }) => Promise<PodMember | null>;
18
+ reset: () => void;
19
+ }
20
+ export declare function useUpdatePodMemberRole({ client, podId, memberId, enabled, onSuccess, onError, }: UseUpdatePodMemberRoleOptions): UseUpdatePodMemberRoleResult;
@@ -0,0 +1,50 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { normalizeError, resolvePodId } from "./utils.js";
3
+ export function useUpdatePodMemberRole({ client, podId, memberId = null, enabled = true, onSuccess, onError, }) {
4
+ const [updatedMember, setUpdatedMember] = 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 trimmedMemberId = typeof memberId === "string" ? memberId.trim() : "";
12
+ const updateRole = useCallback(async (role, overrides = {}) => {
13
+ const nextMemberId = typeof overrides.memberId === "string"
14
+ ? overrides.memberId.trim()
15
+ : trimmedMemberId;
16
+ if (!enabled || nextMemberId.length === 0) {
17
+ return null;
18
+ }
19
+ setIsSubmitting(true);
20
+ setError(null);
21
+ try {
22
+ const resolvedPodId = resolvePodId(client, podId);
23
+ const nextMember = await client.podMembers.updateRole(resolvedPodId, nextMemberId, role);
24
+ setUpdatedMember(nextMember);
25
+ onSuccessRef.current?.(nextMember);
26
+ return nextMember;
27
+ }
28
+ catch (mutationError) {
29
+ const normalized = normalizeError(mutationError, "Failed to update pod member role.");
30
+ setError(normalized);
31
+ onErrorRef.current?.(mutationError);
32
+ return null;
33
+ }
34
+ finally {
35
+ setIsSubmitting(false);
36
+ }
37
+ }, [client, enabled, podId, trimmedMemberId]);
38
+ const reset = useCallback(() => {
39
+ setUpdatedMember(null);
40
+ setError(null);
41
+ setIsSubmitting(false);
42
+ }, []);
43
+ return useMemo(() => ({
44
+ updatedMember,
45
+ isSubmitting,
46
+ error,
47
+ updateRole,
48
+ reset,
49
+ }), [error, isSubmitting, reset, updateRole, updatedMember]);
50
+ }
@@ -0,0 +1,24 @@
1
+ import type { LemmaClient } from "../client.js";
2
+ import type { FileResponse } from "../types.js";
3
+ export interface UploadFileInput {
4
+ name?: string;
5
+ directoryPath?: string;
6
+ parentId?: string;
7
+ searchEnabled?: boolean;
8
+ description?: string;
9
+ }
10
+ export interface UseUploadFileOptions {
11
+ client: LemmaClient;
12
+ podId?: string;
13
+ enabled?: boolean;
14
+ onSuccess?: (file: FileResponse) => void;
15
+ onError?: (error: unknown) => void;
16
+ }
17
+ export interface UseUploadFileResult<TFile extends FileResponse = FileResponse> {
18
+ uploadedFile: TFile | null;
19
+ isSubmitting: boolean;
20
+ error: Error | null;
21
+ upload: (file: Blob, options?: UploadFileInput) => Promise<TFile | null>;
22
+ reset: () => void;
23
+ }
24
+ export declare function useUploadFile<TFile extends FileResponse = FileResponse>({ client, podId, enabled, onSuccess, onError, }: UseUploadFileOptions): UseUploadFileResult<TFile>;
@@ -0,0 +1,46 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { normalizeError, resolvePodClient } from "./utils.js";
3
+ export function useUploadFile({ client, podId, enabled = true, onSuccess, onError, }) {
4
+ const [uploadedFile, setUploadedFile] = 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 upload = useCallback(async (file, options = {}) => {
12
+ if (!enabled) {
13
+ return null;
14
+ }
15
+ setIsSubmitting(true);
16
+ setError(null);
17
+ try {
18
+ const scopedClient = resolvePodClient(client, podId);
19
+ const nextFile = await scopedClient.files.upload(file, options);
20
+ setUploadedFile(nextFile);
21
+ onSuccessRef.current?.(nextFile);
22
+ return nextFile;
23
+ }
24
+ catch (uploadError) {
25
+ const normalized = normalizeError(uploadError, "Failed to upload file.");
26
+ setError(normalized);
27
+ onErrorRef.current?.(uploadError);
28
+ return null;
29
+ }
30
+ finally {
31
+ setIsSubmitting(false);
32
+ }
33
+ }, [client, enabled, podId]);
34
+ const reset = useCallback(() => {
35
+ setUploadedFile(null);
36
+ setError(null);
37
+ setIsSubmitting(false);
38
+ }, []);
39
+ return useMemo(() => ({
40
+ uploadedFile,
41
+ isSubmitting,
42
+ error,
43
+ upload,
44
+ reset,
45
+ }), [error, isSubmitting, reset, uploadedFile, upload]);
46
+ }
@@ -1,5 +1,5 @@
1
1
  import type { LemmaClient } from "../client.js";
2
- import type { FlowRun, FlowStartType, Workflow, WorkflowRunInputs } from "../types.js";
2
+ import type { FlowRun, Workflow, WorkflowStartType, WorkflowRunInputs } from "../types.js";
3
3
  import { type UseFlowSessionResult } from "./useFlowSession.js";
4
4
  export interface UseWorkflowStartOptions {
5
5
  client: LemmaClient;
@@ -15,7 +15,7 @@ export interface UseWorkflowStartOptions {
15
15
  }
16
16
  export interface UseWorkflowStartResult extends Omit<UseFlowSessionResult, "start" | "listHistory"> {
17
17
  workflow: Workflow | null;
18
- startType: FlowStartType | "MANUAL";
18
+ startType: WorkflowStartType | "MANUAL";
19
19
  inputSchema: Record<string, unknown> | null;
20
20
  inputUiSchema: Record<string, unknown> | null;
21
21
  isLoadingWorkflow: boolean;
@@ -0,0 +1,20 @@
1
+ import type { ColumnSchema } from "./types.js";
2
+ export interface RecordDetailFieldGroupDefinition {
3
+ label: string;
4
+ fields: string[];
5
+ }
6
+ export declare function detectRecordTitleColumn(columns: ColumnSchema[]): ColumnSchema | undefined;
7
+ export declare function detectRecordDescriptionColumn(columns: ColumnSchema[]): ColumnSchema | undefined;
8
+ export declare function detectRecordStatusColumn(columns: ColumnSchema[]): ColumnSchema | undefined;
9
+ export declare function isDefaultRecordDetailHiddenField(name: string): boolean;
10
+ export declare function buildDefaultRecordDetailFieldGroups(columns: ColumnSchema[], options?: {
11
+ hiddenFields?: string[];
12
+ titleField?: string;
13
+ descriptionField?: string;
14
+ statusField?: string;
15
+ identifierField?: string;
16
+ }): RecordDetailFieldGroupDefinition[];
17
+ export declare function humanizeRecordFieldName(value: string): string;
18
+ export declare function formatRecordPlainValue(value: unknown): string;
19
+ export declare function formatRecordDisplayValue(value: unknown): string;
20
+ export declare function formatRecordDateDisplayValue(value: unknown, options?: Intl.DateTimeFormatOptions): string;
@@ -0,0 +1,78 @@
1
+ export function detectRecordTitleColumn(columns) {
2
+ return columns.find((column) => !column.system && !column.auto && !column.computed && /title|name|subject|label/i.test(column.name));
3
+ }
4
+ export function detectRecordDescriptionColumn(columns) {
5
+ return columns.find((column) => !column.system
6
+ && !column.auto
7
+ && !column.computed
8
+ && column.type === "TEXT"
9
+ && /description|summary|body|content|notes|reason/i.test(column.name));
10
+ }
11
+ export function detectRecordStatusColumn(columns) {
12
+ return columns.find((column) => /status|state|stage/i.test(column.name));
13
+ }
14
+ export function isDefaultRecordDetailHiddenField(name) {
15
+ return name === "id" || name === "created_at" || name === "updated_at";
16
+ }
17
+ export function buildDefaultRecordDetailFieldGroups(columns, options = {}) {
18
+ const excluded = new Set([
19
+ ...(options.hiddenFields ?? []),
20
+ options.titleField,
21
+ options.descriptionField,
22
+ options.statusField,
23
+ options.identifierField,
24
+ ].filter((value) => Boolean(value)));
25
+ const displayable = columns.filter((column) => !column.system
26
+ && !column.auto
27
+ && !column.computed
28
+ && !isDefaultRecordDetailHiddenField(column.name)
29
+ && !excluded.has(column.name));
30
+ if (displayable.length === 0)
31
+ return [];
32
+ return [
33
+ {
34
+ label: "Details",
35
+ fields: displayable.map((column) => column.name),
36
+ },
37
+ ];
38
+ }
39
+ export function humanizeRecordFieldName(value) {
40
+ return value
41
+ .replace(/[_\.]/g, " ")
42
+ .replace(/\s+/g, " ")
43
+ .trim()
44
+ .replace(/\b\w/g, (match) => match.toUpperCase());
45
+ }
46
+ export function formatRecordPlainValue(value) {
47
+ if (value == null || value === "")
48
+ return "";
49
+ if (value instanceof Date)
50
+ return formatRecordDateDisplayValue(value);
51
+ if (typeof value === "boolean")
52
+ return value ? "Yes" : "No";
53
+ if (typeof value === "number")
54
+ return value.toLocaleString();
55
+ if (Array.isArray(value))
56
+ return value.map(formatRecordPlainValue).filter(Boolean).join(", ");
57
+ if (typeof value === "object")
58
+ return JSON.stringify(value);
59
+ return String(value);
60
+ }
61
+ export function formatRecordDisplayValue(value) {
62
+ return formatRecordPlainValue(value) || "Not set";
63
+ }
64
+ export function formatRecordDateDisplayValue(value, options) {
65
+ if (value == null || value === "")
66
+ return "Not set";
67
+ const date = value instanceof Date ? value : new Date(String(value));
68
+ if (Number.isNaN(date.getTime()))
69
+ return String(value);
70
+ return new Intl.DateTimeFormat(undefined, {
71
+ month: "short",
72
+ day: "numeric",
73
+ year: "numeric",
74
+ hour: "numeric",
75
+ minute: "2-digit",
76
+ ...options,
77
+ }).format(date);
78
+ }
@@ -22,9 +22,13 @@ export interface BuildRecordPayloadResult {
22
22
  errors: Record<string, string>;
23
23
  isValid: boolean;
24
24
  }
25
+ export declare const DEFAULT_RECORD_FORM_HIDDEN_FIELDS: readonly ["id", "created_at", "updated_at", "creator_user_id", "sort_order"];
25
26
  export declare function getRecordFieldKind(column: ColumnSchema): RecordSchemaFieldKind;
26
27
  export declare function buildRecordSchemaFields(table: Table): RecordSchemaField[];
27
28
  export declare function getEditableRecordFields(table: Table): RecordSchemaField[];
29
+ export declare function orderRecordSchemaFields<T extends {
30
+ name: string;
31
+ }>(fields: T[], fieldOrder?: string[]): T[];
28
32
  export declare function formatRecordValueForForm(column: ColumnSchema, value: unknown): unknown;
29
33
  export declare function buildRecordFormValues(table: Table, values?: Record<string, unknown>): Record<string, unknown>;
30
34
  export declare function buildRecordPayload(table: Table, values: Record<string, unknown>, options?: BuildRecordPayloadOptions): BuildRecordPayloadResult;
@@ -1,5 +1,12 @@
1
1
  import { parseForeignKeyReference } from "./datastore-query.js";
2
2
  import { DatastoreDataType } from "./types.js";
3
+ export const DEFAULT_RECORD_FORM_HIDDEN_FIELDS = [
4
+ "id",
5
+ "created_at",
6
+ "updated_at",
7
+ "creator_user_id",
8
+ "sort_order",
9
+ ];
3
10
  function sentenceCase(value) {
4
11
  return value
5
12
  .replace(/_/g, " ")
@@ -101,6 +108,15 @@ export function buildRecordSchemaFields(table) {
101
108
  export function getEditableRecordFields(table) {
102
109
  return buildRecordSchemaFields(table).filter((field) => !field.readOnly);
103
110
  }
111
+ export function orderRecordSchemaFields(fields, fieldOrder) {
112
+ if (!fieldOrder?.length)
113
+ return fields;
114
+ const ordered = fieldOrder
115
+ .map((name) => fields.find((field) => field.name === name))
116
+ .filter((field) => field !== undefined);
117
+ const remaining = fields.filter((field) => !fieldOrder.includes(field.name));
118
+ return [...ordered, ...remaining];
119
+ }
104
120
  export function formatRecordValueForForm(column, value) {
105
121
  const kind = getRecordFieldKind(column);
106
122
  if (value === null || typeof value === "undefined") {
package/dist/types.d.ts CHANGED
@@ -52,6 +52,8 @@ export type TaskMessage = TaskMessageResponse;
52
52
  export type FunctionRun = FunctionRunResponse;
53
53
  export type FlowRun = FlowRunEntity;
54
54
  export type Workflow = FlowResponse;
55
+ export type WorkflowStart = Workflow["start"];
56
+ export type WorkflowStartType = NonNullable<WorkflowStart>["type"];
55
57
  export type Table = TableResponse;
56
58
  export type TableColumn = ColumnSchema;
57
59
  export type DatastoreQueryResult = DatastoreQueryResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lemma-sdk",
3
- "version": "0.2.33",
3
+ "version": "0.2.35",
4
4
  "description": "Official TypeScript SDK for Lemma pod-scoped APIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,5 +0,0 @@
1
- export type EmailSurfaceConfigCreate = {
2
- account_id?: (string | null);
3
- inbox_email?: (string | null);
4
- type?: string;
5
- };
@@ -1,16 +0,0 @@
1
- import type { FlowStart_Output } from './FlowStart_Output.js';
2
- /**
3
- * Represents an installed flow instance.
4
- * Associate a Flow definition with a specific Trigger (Schedule or Event).
5
- */
6
- export type FlowInstallEntity = {
7
- created_at?: string;
8
- flow_id: string;
9
- flow_start: FlowStart_Output;
10
- id?: string;
11
- is_active?: boolean;
12
- pod_id: string;
13
- trigger_id?: (string | null);
14
- updated_at?: string;
15
- user_id: string;
16
- };
@@ -1,6 +0,0 @@
1
- export declare enum FlowStartType {
2
- MANUAL = "MANUAL",
3
- SCHEDULED = "SCHEDULED",
4
- EVENT = "EVENT",
5
- DATASTORE_EVENT = "DATASTORE_EVENT"
6
- }
@@ -1,11 +0,0 @@
1
- /* generated using openapi-typescript-codegen -- do not edit */
2
- /* istanbul ignore file */
3
- /* tslint:disable */
4
- /* eslint-disable */
5
- export var FlowStartType;
6
- (function (FlowStartType) {
7
- FlowStartType["MANUAL"] = "MANUAL";
8
- FlowStartType["SCHEDULED"] = "SCHEDULED";
9
- FlowStartType["EVENT"] = "EVENT";
10
- FlowStartType["DATASTORE_EVENT"] = "DATASTORE_EVENT";
11
- })(FlowStartType || (FlowStartType = {}));