primitive-functions 0.1.0-alpha.0 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.d.ts +929 -28
  2. package/index.js +57 -1
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -39,7 +39,7 @@ export interface PrimitivePlatformError extends Error {
39
39
 
40
40
  /**
41
41
  * The typed HTTP profile, generated from the platform's OpenAPI document. Its
42
- * namespaces mirror the operation ids: databaseTypeConfigs, databases, documents, functions.
42
+ * namespaces mirror the operation ids: analytics, blobBuckets, collections, configVars, connections, databaseTypeConfigs, databases, documents, email, functions, gemini, groups, integrations, iterations, llm, locks, notifications, prompts, resourceMetadata, secrets, users.
43
43
  * Methods take one options object carrying the operation's path parameters,
44
44
  * query parameters, request headers (under their wire names) and `body`.
45
45
  *
@@ -51,6 +51,274 @@ export interface PrimitivePlatformError extends Error {
51
51
  * hiding them would make a route's availability look like a typo.
52
52
  */
53
53
  export interface FunctionApi {
54
+ "analytics": {
55
+ /** `analytics.cohortRetention` — GET /analytics/cohort-retention. Cohort retention metrics */
56
+ "cohortRetention"(args?: {
57
+ "current_timestamp"?: string | number | boolean;
58
+ "_bust"?: string | number | boolean;
59
+ }): Promise<any>;
60
+ /** `analytics.dailyActive` — GET /analytics/daily-active. Daily active user time series */
61
+ "dailyActive"(args?: {
62
+ "windowDays"?: string | number | boolean;
63
+ "current_timestamp"?: string | number | boolean;
64
+ "_bust"?: string | number | boolean;
65
+ }): Promise<any>;
66
+ /** `analytics.errorGroups` — GET /analytics/errors/groups. Group failure events by fingerprint with per-day count buckets */
67
+ "errorGroups"(args?: {
68
+ "windowDays"?: string | number | boolean;
69
+ "limit"?: string | number | boolean;
70
+ "current_timestamp"?: string | number | boolean;
71
+ "_bust"?: string | number | boolean;
72
+ "filter"?: Record<string, Record<string, string | number | boolean | Array<string | number | boolean>>>;
73
+ }): Promise<any>;
74
+ /** `analytics.integrationUsage` — GET /analytics/integrations. Integration usage metrics */
75
+ "integrationUsage"(args?: {
76
+ "windowDays"?: string | number | boolean;
77
+ "current_timestamp"?: string | number | boolean;
78
+ "_bust"?: string | number | boolean;
79
+ }): Promise<any>;
80
+ /** `analytics.listEvents` — GET /analytics/events. List analytics events */
81
+ "listEvents"(args?: {
82
+ "windowDays"?: string | number | boolean;
83
+ "page"?: string | number | boolean;
84
+ "current_timestamp"?: string | number | boolean;
85
+ "_bust"?: string | number | boolean;
86
+ "filter"?: Record<string, Record<string, string | number | boolean | Array<string | number | boolean>>>;
87
+ }): Promise<any>;
88
+ /** `analytics.listEventsGrouped` — GET /analytics/events/grouped. List analytics events grouped by dimension */
89
+ "listEventsGrouped"(args?: {
90
+ "windowDays"?: string | number | boolean;
91
+ "groupBy"?: string | number | boolean;
92
+ "current_timestamp"?: string | number | boolean;
93
+ "_bust"?: string | number | boolean;
94
+ "filter"?: Record<string, Record<string, string | number | boolean | Array<string | number | boolean>>>;
95
+ }): Promise<any>;
96
+ /** `analytics.overviewDau` — GET /analytics/overview/dau. Daily active users overview */
97
+ "overviewDau"(args?: {
98
+ "current_timestamp"?: string | number | boolean;
99
+ "_bust"?: string | number | boolean;
100
+ }): Promise<any>;
101
+ /** `analytics.overviewGrowth` — GET /analytics/overview/growth. User growth overview */
102
+ "overviewGrowth"(args?: {
103
+ "windowDays"?: string | number | boolean;
104
+ "current_timestamp"?: string | number | boolean;
105
+ "_bust"?: string | number | boolean;
106
+ }): Promise<any>;
107
+ /** `analytics.overviewMau` — GET /analytics/overview/mau. Monthly active users overview */
108
+ "overviewMau"(args?: {
109
+ "current_timestamp"?: string | number | boolean;
110
+ "_bust"?: string | number | boolean;
111
+ }): Promise<any>;
112
+ /** `analytics.overviewWau` — GET /analytics/overview/wau. Weekly active users overview */
113
+ "overviewWau"(args?: {
114
+ "current_timestamp"?: string | number | boolean;
115
+ "_bust"?: string | number | boolean;
116
+ }): Promise<any>;
117
+ /** `analytics.rollingActive` — GET /analytics/rolling-active. Rolling active user time series */
118
+ "rollingActive"(args?: {
119
+ "windowDays"?: string | number | boolean;
120
+ "current_timestamp"?: string | number | boolean;
121
+ "_bust"?: string | number | boolean;
122
+ }): Promise<any>;
123
+ /** `analytics.searchUsers` — GET /analytics/users/search. Search app users for analytics */
124
+ "searchUsers"(args?: {
125
+ "q"?: string | number | boolean;
126
+ "limit"?: string | number | boolean;
127
+ "current_timestamp"?: string | number | boolean;
128
+ "_bust"?: string | number | boolean;
129
+ }): Promise<any>;
130
+ /** `analytics.topPrompts` — GET /analytics/prompts/top. List the most-executed prompts */
131
+ "topPrompts"(args?: {
132
+ "windowDays"?: string | number | boolean;
133
+ "limit"?: string | number | boolean;
134
+ "current_timestamp"?: string | number | boolean;
135
+ "_bust"?: string | number | boolean;
136
+ }): Promise<any>;
137
+ /** `analytics.topUsers` — GET /analytics/users/top. List the most active users */
138
+ "topUsers"(args?: {
139
+ "windowDays"?: string | number | boolean;
140
+ "limit"?: string | number | boolean;
141
+ "current_timestamp"?: string | number | boolean;
142
+ "_bust"?: string | number | boolean;
143
+ }): Promise<any>;
144
+ /** `analytics.topWorkflows` — GET /analytics/workflows/top. List the most-run workflows */
145
+ "topWorkflows"(args?: {
146
+ "windowDays"?: string | number | boolean;
147
+ "limit"?: string | number | boolean;
148
+ "current_timestamp"?: string | number | boolean;
149
+ "_bust"?: string | number | boolean;
150
+ }): Promise<any>;
151
+ /** `analytics.userDetail` — GET /analytics/users/{userUlid}/detail. Detailed analytics for a single user */
152
+ "userDetail"(args: {
153
+ "userUlid": string | number;
154
+ "current_timestamp"?: string | number | boolean;
155
+ "_bust"?: string | number | boolean;
156
+ }): Promise<any>;
157
+ /** `analytics.userSnapshot` — GET /analytics/users/{userUlid}/snapshot. Activity snapshot for a single user */
158
+ "userSnapshot"(args: {
159
+ "userUlid": string | number;
160
+ "current_timestamp"?: string | number | boolean;
161
+ "_bust"?: string | number | boolean;
162
+ }): Promise<any>;
163
+ /** `analytics.writeForUser` — POST /analytics/write-for-user. Write an analytics event for a subject user under a grant */
164
+ "writeForUser"(args: {
165
+ body: unknown;
166
+ }): Promise<any>;
167
+ };
168
+ "blobBuckets": {
169
+ /** `blobBuckets.createBucket` — POST /blob-buckets. Create a blob bucket */
170
+ "createBucket"(args: {
171
+ body: unknown;
172
+ }): Promise<any>;
173
+ /** `blobBuckets.delete` — DELETE /blob-buckets/{bucketId}/blobs/{blobId}. Delete a blob */
174
+ "delete"(args: {
175
+ "bucketId": string | number;
176
+ "blobId": string | number;
177
+ }): Promise<any>;
178
+ /** `blobBuckets.deleteBatch` — POST /blob-buckets/{bucketId}/blobs/delete. Batch delete blobs from a bucket */
179
+ "deleteBatch"(args: {
180
+ "bucketId": string | number;
181
+ body: unknown;
182
+ }): Promise<any>;
183
+ /** `blobBuckets.deleteBucket` — DELETE /blob-buckets/{bucketId}. Delete a blob bucket */
184
+ "deleteBucket"(args: {
185
+ "bucketId": string | number;
186
+ }): Promise<any>;
187
+ /** `blobBuckets.download` — GET /blob-buckets/{bucketId}/blobs/{blobId}. Download a blob (anonymous allowed for public buckets) */
188
+ "download"(args: {
189
+ "bucketId": string | number;
190
+ "blobId": string | number;
191
+ "disposition"?: string | number | boolean;
192
+ }): Promise<Uint8Array>;
193
+ /** `blobBuckets.downloadSigned` — GET /blob-buckets/{bucketId}/blobs/{blobId}/signed. Download a blob via a signed URL token */
194
+ "downloadSigned"(args: {
195
+ "bucketId": string | number;
196
+ "blobId": string | number;
197
+ "token"?: string | number | boolean;
198
+ }): Promise<Uint8Array>;
199
+ /** `blobBuckets.getBucket` — GET /blob-buckets/{bucketId}. Get a blob bucket by id */
200
+ "getBucket"(args: {
201
+ "bucketId": string | number;
202
+ }): Promise<any>;
203
+ /** `blobBuckets.getMetadata` — GET /blob-buckets/{bucketId}/blobs/{blobId}/metadata. Get blob metadata (anonymous allowed for public buckets) */
204
+ "getMetadata"(args: {
205
+ "bucketId": string | number;
206
+ "blobId": string | number;
207
+ }): Promise<any>;
208
+ /** `blobBuckets.getSignedUrl` — POST /blob-buckets/{bucketId}/blobs/{blobId}/signed-url. Create a signed download URL for a blob */
209
+ "getSignedUrl"(args: {
210
+ "bucketId": string | number;
211
+ "blobId": string | number;
212
+ body?: unknown;
213
+ }): Promise<any>;
214
+ /** `blobBuckets.list` — GET /blob-buckets/{bucketId}/blobs. List blobs in a bucket (anonymous allowed for public buckets) */
215
+ "list"(args: {
216
+ "bucketId": string | number;
217
+ "limit"?: string | number | boolean;
218
+ "cursor"?: string | number | boolean;
219
+ }): Promise<any>;
220
+ /** `blobBuckets.listBuckets` — GET /blob-buckets. List blob buckets */
221
+ "listBuckets"(args?: Record<string, never>): Promise<any>;
222
+ /** `blobBuckets.updateBucket` — PATCH /blob-buckets/{bucketId}. Update a blob bucket */
223
+ "updateBucket"(args: {
224
+ "bucketId": string | number;
225
+ body: unknown;
226
+ }): Promise<any>;
227
+ /** `blobBuckets.upload` — POST /blob-buckets/{bucketId}/blobs. Upload a blob to a bucket */
228
+ "upload"(args: {
229
+ "bucketId": string | number;
230
+ "X-Blob-Filename": string | number;
231
+ "X-Blob-Tags"?: string | number;
232
+ "Content-Type"?: string | number;
233
+ body: ArrayBuffer | Uint8Array | string;
234
+ }): Promise<any>;
235
+ };
236
+ "collections": {
237
+ /** `collections.addDocument` — POST /collections/{collectionId}/documents. Add a document to a collection */
238
+ "addDocument"(args: {
239
+ "collectionId": string | number;
240
+ body: unknown;
241
+ }): Promise<any>;
242
+ /** `collections.addMember` — POST /collections/{collectionId}/members. Add a member to a collection */
243
+ "addMember"(args: {
244
+ "collectionId": string | number;
245
+ body: unknown;
246
+ }): Promise<any>;
247
+ /** `collections.create` — POST /collections. Create a collection */
248
+ "create"(args: {
249
+ body: unknown;
250
+ }): Promise<any>;
251
+ /** `collections.delete` — DELETE /collections/{collectionId}. Delete a collection */
252
+ "delete"(args: {
253
+ "collectionId": string | number;
254
+ }): Promise<any>;
255
+ /** `collections.get` — GET /collections/{collectionId}. Get a collection by id */
256
+ "get"(args: {
257
+ "collectionId": string | number;
258
+ }): Promise<any>;
259
+ /** `collections.getAccess` — GET /collections/{collectionId}/access. Get a collection's access summary */
260
+ "getAccess"(args: {
261
+ "collectionId": string | number;
262
+ }): Promise<any>;
263
+ /** `collections.grantGroupPermission` — POST /collections/{collectionId}/group-permissions. Grant a group permission on a collection */
264
+ "grantGroupPermission"(args: {
265
+ "collectionId": string | number;
266
+ body: unknown;
267
+ }): Promise<any>;
268
+ /** `collections.list` — GET /collections. List collections */
269
+ "list"(args?: {
270
+ "limit"?: string | number | boolean;
271
+ "cursor"?: string | number | boolean;
272
+ }): Promise<any>;
273
+ /** `collections.listCollectionsForDocument` — GET /documents/{documentId}/collections. List collections a document belongs to (reverse lookup) */
274
+ "listCollectionsForDocument"(args: {
275
+ "documentId": string | number;
276
+ }): Promise<any>;
277
+ /** `collections.listDocuments` — GET /collections/{collectionId}/documents. List documents in a collection */
278
+ "listDocuments"(args: {
279
+ "collectionId": string | number;
280
+ "limit"?: string | number | boolean;
281
+ "cursor"?: string | number | boolean;
282
+ }): Promise<any>;
283
+ /** `collections.listPendingInvitations` — GET /collections/{collectionId}/pending-invitations. List a collection's pending invitations */
284
+ "listPendingInvitations"(args: {
285
+ "collectionId": string | number;
286
+ }): Promise<any>;
287
+ /** `collections.removeDocument` — DELETE /collections/{collectionId}/documents/{documentId}. Remove a document from a collection */
288
+ "removeDocument"(args: {
289
+ "collectionId": string | number;
290
+ "documentId": string | number;
291
+ }): Promise<any>;
292
+ /** `collections.removeMember` — DELETE /collections/{collectionId}/members/{userId}. Remove a member from a collection */
293
+ "removeMember"(args: {
294
+ "collectionId": string | number;
295
+ "userId": string | number;
296
+ }): Promise<any>;
297
+ /** `collections.revokeGroupPermission` — DELETE /collections/{collectionId}/group-permissions/{groupType}/{groupId}. Revoke a group permission on a collection */
298
+ "revokeGroupPermission"(args: {
299
+ "collectionId": string | number;
300
+ "groupType": string | number;
301
+ "groupId": string | number;
302
+ }): Promise<any>;
303
+ /** `collections.update` — PATCH /collections/{collectionId}. Update a collection */
304
+ "update"(args: {
305
+ "collectionId": string | number;
306
+ body: unknown;
307
+ }): Promise<any>;
308
+ };
309
+ "configVars": {
310
+ /** `configVars.get` — GET /config-vars/{name}. Read an app config var under a server function's grants */
311
+ "get"(args: {
312
+ "name": string | number;
313
+ }): Promise<any>;
314
+ };
315
+ "connections": {
316
+ /** `connections.send` — POST /connections/{connectionId}/send. Send a realtime message to one connection of this app */
317
+ "send"(args: {
318
+ "connectionId": string | number;
319
+ body: unknown;
320
+ }): Promise<any>;
321
+ };
54
322
  "databaseTypeConfigs": {
55
323
  /** `databaseTypeConfigs.create` — POST /databases/types. Create a database type */
56
324
  "create"(args: {
@@ -341,6 +609,12 @@ export interface FunctionApi {
341
609
  "databaseId": string | number;
342
610
  "userId": string | number;
343
611
  }): Promise<any>;
612
+ /** `databases.runOperation` — POST /databases/{databaseId}/operations/{name}/run. Run a database operation under a server function's grants */
613
+ "runOperation"(args: {
614
+ "databaseId": string | number;
615
+ "name": string | number;
616
+ body?: unknown;
617
+ }): Promise<any>;
344
618
  /** `databases.transferOwnership` — POST /databases/{databaseId}/permissions/transfer. Transfer database ownership */
345
619
  "transferOwnership"(args: {
346
620
  "databaseId": string | number;
@@ -439,11 +713,6 @@ export interface FunctionApi {
439
713
  "create"(args: {
440
714
  body: unknown;
441
715
  }): Promise<any>;
442
- /** `documents.createInvitation` — POST /documents/{documentId}/invitations. Send an invitation to collaborate on a document */
443
- "createInvitation"(args: {
444
- "documentId": string | number;
445
- body: unknown;
446
- }): Promise<any>;
447
716
  /** `documents.createWithAlias` — POST /documents/create-with-alias. Create a document and bind it to an alias */
448
717
  "createWithAlias"(args: {
449
718
  body: unknown;
@@ -475,20 +744,10 @@ export interface FunctionApi {
475
744
  "debugStats"(args: {
476
745
  "documentId": string | number;
477
746
  }): Promise<any>;
478
- /** `documents.declineInvitation` — POST /documents/{documentId}/invitations/{invitationId}/decline. Decline a document invitation (invitee only) */
479
- "declineInvitation"(args: {
480
- "documentId": string | number;
481
- "invitationId": string | number;
482
- }): Promise<any>;
483
747
  /** `documents.delete` — DELETE /documents/{documentId}. Delete a document */
484
748
  "delete"(args: {
485
749
  "documentId": string | number;
486
750
  }): Promise<any>;
487
- /** `documents.deleteInvitation` — DELETE /documents/{documentId}/invitations/{invitationId}. Cancel a pending document invitation */
488
- "deleteInvitation"(args: {
489
- "documentId": string | number;
490
- "invitationId": string | number;
491
- }): Promise<any>;
492
751
  /** `documents.denyAccessRequest` — POST /documents/{documentId}/access-requests/{requestId}/deny. Deny a document access request */
493
752
  "denyAccessRequest"(args: {
494
753
  "documentId": string | number;
@@ -556,8 +815,6 @@ export interface FunctionApi {
556
815
  "documentId": string | number;
557
816
  body: unknown;
558
817
  }): Promise<any>;
559
- /** `documents.list` — GET /documents. List documents the caller can access */
560
- "list"(args?: Record<string, never>): Promise<any>;
561
818
  /** `documents.listAccessRequests` — GET /documents/{documentId}/access-requests. List access requests for a document */
562
819
  "listAccessRequests"(args: {
563
820
  "documentId": string | number;
@@ -566,10 +823,6 @@ export interface FunctionApi {
566
823
  "listGroupPermissions"(args: {
567
824
  "documentId": string | number;
568
825
  }): Promise<any>;
569
- /** `documents.listInvitations` — GET /documents/{documentId}/invitations. List invitations issued for a document */
570
- "listInvitations"(args: {
571
- "documentId": string | number;
572
- }): Promise<any>;
573
826
  /** `documents.listPendingInvitations` — GET /documents/{documentId}/pending-invitations. List a document's pending (deferred) invitations */
574
827
  "listPendingInvitations"(args: {
575
828
  "documentId": string | number;
@@ -666,24 +919,544 @@ export interface FunctionApi {
666
919
  "documentId": string | number;
667
920
  body: unknown;
668
921
  }): Promise<any>;
669
- /** `documents.validateAccess` — POST /documents/{documentId}/validate-access. Validate access to a document (accepts/upgrades pending invitations) */
922
+ /** `documents.validateAccess` — POST /documents/{documentId}/validate-access. Resolve the caller's effective access level for a document */
670
923
  "validateAccess"(args: {
671
924
  "documentId": string | number;
672
925
  }): Promise<any>;
673
926
  };
927
+ "email": {
928
+ /** `email.send` — POST /emails/send. Send an application email under a server function's grant */
929
+ "send"(args: {
930
+ body: unknown;
931
+ }): Promise<any>;
932
+ };
674
933
  "functions": {
675
- /** `functions.invoke` — POST /functions/{functionKey}. Invoke a server function synchronously and return its result */
934
+ /** `functions.invoke` — POST /functions/{functionKey}. Invoke a server function: a synchronous one returns its result, a durable one starts a run */
676
935
  "invoke"(args: {
677
936
  "functionKey": string | number;
678
937
  body?: unknown;
679
938
  }): Promise<any>;
680
939
  };
940
+ "gemini": {
941
+ /** `gemini.countTokens` — POST /gemini/count-tokens. Count tokens for a Gemini request */
942
+ "countTokens"(args: {
943
+ body: unknown;
944
+ }): Promise<any>;
945
+ /** `gemini.generate` — POST /gemini/generate. Generate content with Gemini */
946
+ "generate"(args: {
947
+ body: unknown;
948
+ }): Promise<any>;
949
+ /** `gemini.generateRaw` — POST /gemini/generate-raw. Generate content with Gemini (raw passthrough) */
950
+ "generateRaw"(args: {
951
+ "model"?: string | number | boolean;
952
+ body: unknown;
953
+ }): Promise<any>;
954
+ /** `gemini.models` — GET /gemini/models. List available Gemini models */
955
+ "models"(args?: Record<string, never>): Promise<any>;
956
+ };
957
+ "groups": {
958
+ /** `groups.addMember` — POST /groups/{groupType}/{groupId}/members. Add a member to a group */
959
+ "addMember"(args: {
960
+ "groupType": string | number;
961
+ "groupId": string | number;
962
+ body: unknown;
963
+ }): Promise<any>;
964
+ /** `groups.create` — POST /groups. Create a group */
965
+ "create"(args: {
966
+ body: unknown;
967
+ }): Promise<any>;
968
+ /** `groups.delete` — DELETE /groups/{groupType}/{groupId}. Delete a group */
969
+ "delete"(args: {
970
+ "groupType": string | number;
971
+ "groupId": string | number;
972
+ }): Promise<any>;
973
+ /** `groups.get` — GET /groups/{groupType}/{groupId}. Get a group by type and id */
974
+ "get"(args: {
975
+ "groupType": string | number;
976
+ "groupId": string | number;
977
+ }): Promise<any>;
978
+ /** `groups.list` — GET /groups. List groups */
979
+ "list"(args?: {
980
+ "type"?: string | number | boolean;
981
+ "includeSystem"?: string | number | boolean;
982
+ "limit"?: string | number | boolean;
983
+ "cursor"?: string | number | boolean;
984
+ }): Promise<any>;
985
+ /** `groups.listDatabases` — GET /groups/{groupType}/{groupId}/databases. List databases shared with a group */
986
+ "listDatabases"(args: {
987
+ "groupType": string | number;
988
+ "groupId": string | number;
989
+ }): Promise<any>;
990
+ /** `groups.listDocuments` — GET /groups/{groupType}/{groupId}/documents. List documents shared with a group */
991
+ "listDocuments"(args: {
992
+ "groupType": string | number;
993
+ "groupId": string | number;
994
+ }): Promise<any>;
995
+ /** `groups.listMembers` — GET /groups/{groupType}/{groupId}/members. List a group's members */
996
+ "listMembers"(args: {
997
+ "groupType": string | number;
998
+ "groupId": string | number;
999
+ "limit"?: string | number | boolean;
1000
+ "cursor"?: string | number | boolean;
1001
+ "include"?: string | number | boolean;
1002
+ }): Promise<any>;
1003
+ /** `groups.listPendingInvitations` — GET /groups/{groupType}/{groupId}/pending-invitations. List a group's pending invitations */
1004
+ "listPendingInvitations"(args: {
1005
+ "groupType": string | number;
1006
+ "groupId": string | number;
1007
+ }): Promise<any>;
1008
+ /** `groups.listUserMemberships` — GET /users/{userId}/memberships. List a user's group memberships */
1009
+ "listUserMemberships"(args: {
1010
+ "userId": string | number;
1011
+ "includeSystem"?: string | number | boolean;
1012
+ "type"?: string | number | boolean;
1013
+ }): Promise<any>;
1014
+ /** `groups.removeMember` — DELETE /groups/{groupType}/{groupId}/members/{userId}. Remove a specific member from a group */
1015
+ "removeMember"(args: {
1016
+ "groupType": string | number;
1017
+ "groupId": string | number;
1018
+ "userId": string | number;
1019
+ }): Promise<any>;
1020
+ /** `groups.removeMemberByEmail` — DELETE /groups/{groupType}/{groupId}/members. Remove a group member or pending invitation by email */
1021
+ "removeMemberByEmail"(args: {
1022
+ "groupType": string | number;
1023
+ "groupId": string | number;
1024
+ "email"?: string | number | boolean;
1025
+ }): Promise<any>;
1026
+ /** `groups.update` — PATCH /groups/{groupType}/{groupId}. Update a group */
1027
+ "update"(args: {
1028
+ "groupType": string | number;
1029
+ "groupId": string | number;
1030
+ body: unknown;
1031
+ }): Promise<any>;
1032
+ };
1033
+ "integrations": {
1034
+ /** `integrations.call` — POST /integrations/{integrationKey}/call. Call an integration under a server function's grants */
1035
+ "call"(args: {
1036
+ "integrationKey": string | number;
1037
+ body?: unknown;
1038
+ }): Promise<any>;
1039
+ /** `integrations.list` — GET /integrations. List integrations configured for the app */
1040
+ "list"(args?: Record<string, never>): Promise<any>;
1041
+ /** `integrations.proxy` — POST /integrations/{integrationKey}/proxy. Proxy a request through a configured integration */
1042
+ "proxy"(args: {
1043
+ "integrationKey": string | number;
1044
+ }): Promise<any>;
1045
+ };
1046
+ "iterations": {
1047
+ /** `iterations.get` — GET /iterations/{iterationName}. Get details for a single iteration */
1048
+ "get"(args: {
1049
+ "iterationName": string | number;
1050
+ }): Promise<any>;
1051
+ /** `iterations.list` — GET /iterations. List iteration runs */
1052
+ "list"(args?: Record<string, never>): Promise<any>;
1053
+ /** `iterations.reset` — POST /iterations/{iterationName}/reset. Reset a terminal iteration so the next trigger runs fresh */
1054
+ "reset"(args: {
1055
+ "iterationName": string | number;
1056
+ }): Promise<any>;
1057
+ };
1058
+ "llm": {
1059
+ /** `llm.chat` — POST /llm/chat. Run an LLM chat completion */
1060
+ "chat"(args: {
1061
+ body: unknown;
1062
+ }): Promise<any>;
1063
+ /** `llm.models` — GET /llm/models. List available LLM models */
1064
+ "models"(args?: Record<string, never>): Promise<any>;
1065
+ };
1066
+ "locks": {
1067
+ /** `locks.list` — GET /locks. List all currently-held named locks in the app */
1068
+ "list"(args?: Record<string, never>): Promise<any>;
1069
+ /** `locks.release` — POST /locks/release. Release a held named lock (requires the acquire handle) */
1070
+ "release"(args: {
1071
+ body: unknown;
1072
+ }): Promise<any>;
1073
+ /** `locks.renew` — POST /locks/renew. Extend the lease on a held named lock */
1074
+ "renew"(args: {
1075
+ body: unknown;
1076
+ }): Promise<any>;
1077
+ /** `locks.status` — POST /locks/status. Report the current holder of a named lock */
1078
+ "status"(args: {
1079
+ body: unknown;
1080
+ }): Promise<any>;
1081
+ /** `locks.tryAcquire` — POST /locks/acquire. Attempt to acquire a named lock (single non-blocking attempt) */
1082
+ "tryAcquire"(args: {
1083
+ body: unknown;
1084
+ }): Promise<any>;
1085
+ };
1086
+ "notifications": {
1087
+ /** `notifications.list` — GET /notifications. List the caller's in-app notification inbox (newest first) */
1088
+ "list"(args?: {
1089
+ "limit"?: string | number | boolean;
1090
+ "cursor"?: string | number | boolean;
1091
+ }): Promise<any>;
1092
+ /** `notifications.listDevices` — GET /me/push-tokens. List the caller's registered push devices */
1093
+ "listDevices"(args?: Record<string, never>): Promise<any>;
1094
+ /** `notifications.markAllRead` — POST /notifications/read-all. Mark all of the caller's notifications as read */
1095
+ "markAllRead"(args?: Record<string, never>): Promise<any>;
1096
+ /** `notifications.markRead` — PATCH /notifications/{notificationId}/read. Mark one of the caller's notifications as read */
1097
+ "markRead"(args: {
1098
+ "notificationId": string | number;
1099
+ }): Promise<any>;
1100
+ /** `notifications.registerDevice` — POST /me/push-tokens. Register (upsert) the caller's device push token */
1101
+ "registerDevice"(args: {
1102
+ body: unknown;
1103
+ }): Promise<any>;
1104
+ /** `notifications.send` — POST /notifications/send. Send a notification to an app user (durable in-app inbox row + live WS frame) */
1105
+ "send"(args: {
1106
+ body: unknown;
1107
+ }): Promise<any>;
1108
+ /** `notifications.unreadCount` — GET /notifications/unread-count. Count the caller's unread notifications */
1109
+ "unreadCount"(args?: Record<string, never>): Promise<any>;
1110
+ /** `notifications.unregisterDevice` — DELETE /me/push-tokens/{token}. Unregister one of the caller's device push tokens */
1111
+ "unregisterDevice"(args: {
1112
+ "token": string | number;
1113
+ }): Promise<any>;
1114
+ };
1115
+ "prompts": {
1116
+ /** `prompts.execute` — POST /prompts/{promptKey}/execute. Execute a saved prompt */
1117
+ "execute"(args: {
1118
+ "promptKey": string | number;
1119
+ }): Promise<any>;
1120
+ /** `prompts.run` — POST /prompts/{promptKey}/run. Run a prompt under a server function's grants */
1121
+ "run"(args: {
1122
+ "promptKey": string | number;
1123
+ body?: unknown;
1124
+ }): Promise<any>;
1125
+ };
1126
+ "resourceMetadata": {
1127
+ /** `resourceMetadata.delete` — DELETE /resources/{resourceType}/{resourceId}/metadata/{category}. Delete a resource's metadata for a category (idempotent) */
1128
+ "delete"(args: {
1129
+ "resourceType": string | number;
1130
+ "resourceId": string | number;
1131
+ "category": string | number;
1132
+ }): Promise<any>;
1133
+ /** `resourceMetadata.get` — GET /resources/{resourceType}/{resourceId}/metadata/{category}. Read a resource's metadata for a category */
1134
+ "get"(args: {
1135
+ "resourceType": string | number;
1136
+ "resourceId": string | number;
1137
+ "category": string | number;
1138
+ }): Promise<any>;
1139
+ /** `resourceMetadata.getBatch` — POST /resources/metadata/batch. Batch-read resource metadata (partial success) */
1140
+ "getBatch"(args: {
1141
+ "debug"?: string | number | boolean;
1142
+ body: unknown;
1143
+ }): Promise<any>;
1144
+ /** `resourceMetadata.list` — GET /resources/{resourceType}/{resourceId}/metadata. List all metadata categories on a resource */
1145
+ "list"(args: {
1146
+ "resourceType": string | number;
1147
+ "resourceId": string | number;
1148
+ }): Promise<any>;
1149
+ /** `resourceMetadata.resolve` — POST /metadata/resolve. Resolve a resource by a category's unique metadata value */
1150
+ "resolve"(args: {
1151
+ body: unknown;
1152
+ }): Promise<any>;
1153
+ /** `resourceMetadata.set` — PUT /resources/{resourceType}/{resourceId}/metadata/{category}. Write a resource's metadata for a category */
1154
+ "set"(args: {
1155
+ "resourceType": string | number;
1156
+ "resourceId": string | number;
1157
+ "category": string | number;
1158
+ body: unknown;
1159
+ }): Promise<any>;
1160
+ };
1161
+ "secrets": {
1162
+ /** `secrets.get` — GET /secrets/{name}. Read an app secret under a server function's grants */
1163
+ "get"(args: {
1164
+ "name": string | number;
1165
+ }): Promise<any>;
1166
+ };
1167
+ "users": {
1168
+ /** `users.getBasic` — GET /users/{userId}/basic. Get a user's basic public profile */
1169
+ "getBasic"(args: {
1170
+ "userId": string | number;
1171
+ }): Promise<any>;
1172
+ /** `users.getProfiles` — POST /users/profiles. Look up user profiles in bulk */
1173
+ "getProfiles"(args: {
1174
+ body: unknown;
1175
+ }): Promise<any>;
1176
+ /** `users.list` — GET /users. List app users */
1177
+ "list"(args?: {
1178
+ "email"?: string | number | boolean;
1179
+ "userId"?: string | number | boolean;
1180
+ "name"?: string | number | boolean;
1181
+ "limit"?: string | number | boolean;
1182
+ "cursor"?: string | number | boolean;
1183
+ }): Promise<any>;
1184
+ /** `users.lookup` — GET /users/lookup. Look up a user by identifier */
1185
+ "lookup"(args?: {
1186
+ "email"?: string | number | boolean;
1187
+ }): Promise<any>;
1188
+ /** `users.remove` — DELETE /users/{userId}. Remove a user from the app */
1189
+ "remove"(args: {
1190
+ "userId": string | number;
1191
+ }): Promise<any>;
1192
+ /** `users.send` — POST /users/{userId}/send. Send a realtime message to a member of this app */
1193
+ "send"(args: {
1194
+ "userId": string | number;
1195
+ body: unknown;
1196
+ }): Promise<any>;
1197
+ /** `users.setRole` — PUT /users/{userId}/role. Set a user's app role */
1198
+ "setRole"(args: {
1199
+ "userId": string | number;
1200
+ body: unknown;
1201
+ }): Promise<any>;
1202
+ };
1203
+ }
1204
+
1205
+ /**
1206
+ * The app's database types, model by model — EMPTY here and filled by the
1207
+ * declaration `primitive config push` writes into the config tree's
1208
+ * `functions/` directory (#3182). A tree that has pushed once therefore types
1209
+ * `ctx.db` against its own schemas; one that has not gets the open form and
1210
+ * still compiles.
1211
+ */
1212
+ export interface DatabaseSchemas {}
1213
+
1214
+ /**
1215
+ * The type keys `ctx.db` accepts.
1216
+ *
1217
+ * Every key the augmentation declares, and NOTHING else, once a tree has
1218
+ * pushed: naming a type the app does not have is a compile error. Before that
1219
+ * — an unaugmented tree, a function written before the first push —
1220
+ * `DatabaseSchemas` is empty and `keyof` it is `never`, which would make the
1221
+ * argument unwritable rather than open. So the empty case widens to `string`
1222
+ * and the handle is untyped instead of unusable.
1223
+ */
1224
+ export type DatabaseTypeKeys = [keyof DatabaseSchemas] extends [never]
1225
+ ? string
1226
+ : keyof DatabaseSchemas & string;
1227
+
1228
+ /** A model's row shape, or an open record for a type with no schema. */
1229
+ export type DatabaseModels<K extends string> = K extends keyof DatabaseSchemas
1230
+ ? DatabaseSchemas[K]
1231
+ : Record<string, Record<string, unknown>>;
1232
+
1233
+ /**
1234
+ * The model names one database type addresses — its own, or any name at all
1235
+ * for a type that declares no schema (the DO is schemaless, so a grant on such
1236
+ * a type is legal and there is simply nothing to narrow to).
1237
+ */
1238
+ export type DatabaseModelNames<TModels> = [keyof TModels] extends [never]
1239
+ ? string
1240
+ : keyof TModels & string;
1241
+
1242
+ /** One model's row shape, open when the type declares no schema. */
1243
+ export type DatabaseModelRow<TModels, M extends string> =
1244
+ M extends keyof TModels ? TModels[M] : Record<string, unknown>;
1245
+
1246
+ /**
1247
+ * One model of one database, scoped: the `modelName` every records call needs
1248
+ * is bound once, so a call names an operation and its own arguments.
1249
+ *
1250
+ * Filters and options are ordinary objects. Inline filter typing arrives with
1251
+ * unified schemas — the intent's decision, not an omission — so what is typed
1252
+ * today is the model name and the row shape a read hands back.
1253
+ */
1254
+ export type ModelScopedBody<TBody = Record<string, unknown>> = TBody & {
1255
+ /**
1256
+ * Bound by the handle. Reserved so a body cannot look like a second way to
1257
+ * choose a model: the runtime assigns the handle's own model last, and a row
1258
+ * type that said otherwise would be a lie about what came back.
1259
+ */
1260
+ modelName?: never;
1261
+ };
1262
+
1263
+ /**
1264
+ * One write inside a model-scoped batch. Every batch verb is a write, so a
1265
+ * batch on a model needs that model's write grant whatever the ops are.
1266
+ */
1267
+ export type ModelBatchOperation<TRow> = {
1268
+ op: "save" | "patch" | "delete" | "increment" | "addToSet" | "removeFromSet";
1269
+ id?: string;
1270
+ data?: Partial<TRow>;
1271
+ /** Bound by the handle, for the same reason every other call's is. */
1272
+ modelName?: never;
1273
+ [key: string]: unknown;
1274
+ };
1275
+
1276
+ export interface DatabaseModelHandle<TRow> {
1277
+ query(body?: ModelScopedBody): Promise<{ data: TRow[]; hasMore?: boolean; nextCursor?: string }>;
1278
+ count(body?: ModelScopedBody): Promise<any>;
1279
+ aggregate(body: ModelScopedBody): Promise<any>;
1280
+ save(body: ModelScopedBody<{ id?: string; data: Partial<TRow>; [key: string]: unknown }>): Promise<any>;
1281
+ /** Several writes to THIS model in one request; the binding is per item. */
1282
+ batch(body: {
1283
+ operations: Array<ModelBatchOperation<TRow>>;
1284
+ atomic?: boolean;
1285
+ }): Promise<any>;
1286
+ }
1287
+
1288
+ /** One database, typed by the database TYPE key its grant names. */
1289
+ export interface DatabaseHandle<TModels> {
1290
+ /** The database this handle addresses — part of every query cache key. */
1291
+ databaseId: string;
1292
+ /** The type key this handle was opened with. */
1293
+ databaseType: string;
1294
+ model<M extends DatabaseModelNames<TModels>>(
1295
+ modelName: M
1296
+ ): DatabaseModelHandle<DatabaseModelRow<TModels, M>>;
1297
+ /**
1298
+ * A batch may also SPAN models, and then it names each one itself — the
1299
+ * model-scoped form above is the typed way to write the common case.
1300
+ */
1301
+ batch(body: {
1302
+ operations: Array<Record<string, unknown>>;
1303
+ atomic?: boolean;
1304
+ }): Promise<any>;
1305
+ /** Run one of the database type's prepared operations under this function's grants. */
1306
+ runOperation(name: string, params?: Record<string, unknown>): Promise<any>;
1307
+ }
1308
+
1309
+ /**
1310
+ * One call through a granted integration — #3183.
1311
+ *
1312
+ * `path` is RELATIVE to the integration's `baseUrl`, and the host is the
1313
+ * integration's: the platform resolves and normalizes the path before checking
1314
+ * it against `allowedPaths`, so a protocol-relative path or a `..` segment is
1315
+ * refused rather than silently sending the request somewhere else.
1316
+ */
1317
+ export interface IntegrationCallRequest {
1318
+ /** Must be in the integration's `allowedMethods`. Defaults to its own default. */
1319
+ method?: string;
1320
+ /** Relative to the integration's `baseUrl`. */
1321
+ path?: string;
1322
+ query?: Record<string, unknown>;
1323
+ headers?: Record<string, string>;
1324
+ body?: unknown;
1325
+ /** form-urlencoded body; not combinable with `body`. */
1326
+ form?: Record<string, unknown>;
1327
+ bodyMode?: "json" | "raw" | "multipart";
1328
+ }
1329
+
1330
+ /** What the upstream answered, as the platform saw it. */
1331
+ export interface IntegrationCallResult {
1332
+ status: number;
1333
+ headers: Record<string, string>;
1334
+ body: unknown;
1335
+ durationMs: number;
1336
+ traceId: string;
1337
+ /** Set when the platform or the upstream refused; absent on success. */
1338
+ errorCode?: string;
1339
+ }
1340
+
1341
+ /** What a prompt run is given — the member execute route's own body. */
1342
+ export interface PromptRunArgs {
1343
+ variables?: Record<string, unknown>;
1344
+ /** Run against a different model for this call only. */
1345
+ modelOverride?: string;
1346
+ /** Pin a specific config OF THIS PROMPT; defaults to its active one. */
1347
+ configId?: string;
1348
+ }
1349
+
1350
+ /** The member execute envelope, unchanged on the function path. */
1351
+ export interface PromptRunResult {
1352
+ success: boolean;
1353
+ output: string;
1354
+ error?: string | null;
1355
+ metrics?: Record<string, unknown>;
1356
+ configId: string;
1357
+ }
1358
+
1359
+ /** What a send delivered to. */
1360
+ export interface SendResult {
1361
+ /** Unique live connections the frame was sent to. Zero is a success. */
1362
+ connections: number;
1363
+ /** True when the per-user connection ceiling stopped the fanout. */
1364
+ truncated: boolean;
681
1365
  }
682
1366
 
683
1367
  export interface FunctionContext {
684
1368
  user: FunctionUser;
685
1369
  trigger: FunctionTrigger;
686
1370
  api: FunctionApi;
1371
+ /**
1372
+ * A typed handle over one database. The second argument is the database TYPE
1373
+ * key — the same key a `database:<type>/<model>:read|write` grant names —
1374
+ * and it is what selects the models this handle knows (#3182).
1375
+ */
1376
+ db<K extends DatabaseTypeKeys>(
1377
+ databaseId: string,
1378
+ databaseType: K
1379
+ ): DatabaseHandle<DatabaseModels<K>>;
1380
+ /**
1381
+ * Outbound HTTP, through a granted integration and nowhere else (#3183).
1382
+ *
1383
+ * A function has no raw network access: every `fetch` to a host that is not
1384
+ * the platform answers `FUNCTION_EGRESS_DENIED`, grant or no grant. What an
1385
+ * `integration:<key>` grant buys is this call, which the MAIN WORKER makes on
1386
+ * the function's behalf — which is why the integration's `{{secrets.*}}`
1387
+ * credentials can be injected into the request without ever being visible to
1388
+ * the code that asked for it.
1389
+ */
1390
+ integrations: {
1391
+ call(
1392
+ integrationKey: string,
1393
+ request?: IntegrationCallRequest
1394
+ ): Promise<IntegrationCallResult>;
1395
+ };
1396
+ /**
1397
+ * Run one of the app's prompts, under a `prompt:<key>` grant (#3183).
1398
+ *
1399
+ * The prompt's `accessRule` is not consulted — it states which MEMBERS may
1400
+ * execute the prompt from a client, and the grant is what authorizes this
1401
+ * call. The provider request is bounded by the invocation's own deadline.
1402
+ */
1403
+ prompts: {
1404
+ run(promptKey: string, args?: PromptRunArgs): Promise<PromptRunResult>;
1405
+ };
1406
+ /**
1407
+ * The value of one app secret, under a `secret:<NAME>` grant (#3183).
1408
+ *
1409
+ * Prefer `ctx.integrations.call` when the secret is a credential FOR an
1410
+ * integration: there the value is injected by the platform and never enters
1411
+ * the sandbox at all. This is for the cases an integration cannot express.
1412
+ *
1413
+ * Rejects with `FUNCTION_SECRET_NOT_FOUND` when the grant names a value
1414
+ * this environment has not been given — secrets are provisioned per
1415
+ * environment, out of band from the push.
1416
+ */
1417
+ secret(name: string): Promise<string>;
1418
+ /** The value of one app config var, under a `var:<NAME>` grant (#3183). */
1419
+ configVar(name: string): Promise<string>;
1420
+ /**
1421
+ * Realtime messages to this app's clients, under a `users:send` grant
1422
+ * (#3183).
1423
+ *
1424
+ * The recipient's client receives a `direct.message` frame carrying this
1425
+ * payload and the sending function's key. Presence is not guaranteed: a
1426
+ * member with no live socket answers `{ connections: 0 }` rather than an
1427
+ * error.
1428
+ */
1429
+ users: {
1430
+ send(userId: string, payload: unknown): Promise<SendResult>;
1431
+ };
1432
+ /** The same frame to ONE connection, under a `connections:send` grant. */
1433
+ connections: {
1434
+ send(connectionId: string, payload: unknown): Promise<SendResult>;
1435
+ };
1436
+ }
1437
+
1438
+ /**
1439
+ * The durable step handle — Cloudflare Workflows' `WorkflowStep`, forwarded
1440
+ * untouched, so `step.do` results are memoized and `step.sleep` hibernates.
1441
+ *
1442
+ * A SYNCHRONOUS invocation gets a passthrough shim of the same shape, so a body
1443
+ * written for durable mode runs either way: `do` executes the body (nothing to
1444
+ * memoize into without an engine), `sleep` resolves immediately (the sync
1445
+ * ceiling is seconds), and `waitForEvent` throws `STEP_NOT_AVAILABLE`.
1446
+ */
1447
+ export interface FunctionStep {
1448
+ do<T>(name: string, body: () => T | Promise<T>): Promise<T>;
1449
+ do<T>(
1450
+ name: string,
1451
+ config: Record<string, unknown>,
1452
+ body: () => T | Promise<T>
1453
+ ): Promise<T>;
1454
+ sleep(name: string, duration: number | string): Promise<void>;
1455
+ sleepUntil(name: string, timestamp: Date | number): Promise<void>;
1456
+ waitForEvent<T = unknown>(
1457
+ name: string,
1458
+ options: Record<string, unknown>
1459
+ ): Promise<T>;
687
1460
  }
688
1461
 
689
1462
  export declare const SDK_STUB_VERSION: string;
@@ -692,15 +1465,143 @@ export declare const SDK_STUB_VERSION: string;
692
1465
  * Declare a server function's handler.
693
1466
  *
694
1467
  * Both authoring styles reach the platform bootstrap identically — a plain
695
- * default export taking `(input, ctx)` runs exactly as a wrapped one does —
696
- * so this is a typing and intent marker, not a different calling convention.
1468
+ * default export taking `(input, ctx, step)` runs exactly as a wrapped one
1469
+ * does — so this is a typing and intent marker, not a different calling
1470
+ * convention.
1471
+ *
1472
+ * `step` is the third argument in BOTH modes (#3186). A durable run gets the
1473
+ * engine's live `WorkflowStep`; a synchronous one gets a passthrough shim
1474
+ * (`do` runs the body, `sleep` resolves at once, `waitForEvent` throws a
1475
+ * named error), so a durable-authored body can be exercised synchronously.
697
1476
  */
698
1477
  export declare function defineFunction<TInput = unknown, TOutput = unknown>(
699
- handler: (input: TInput, ctx: FunctionContext) => TOutput | Promise<TOutput>
700
- ): (input: TInput, ctx: FunctionContext) => Promise<TOutput>;
1478
+ handler: (
1479
+ input: TInput,
1480
+ ctx: FunctionContext,
1481
+ step: FunctionStep
1482
+ ) => TOutput | Promise<TOutput>
1483
+ ): (
1484
+ input: TInput,
1485
+ ctx: FunctionContext,
1486
+ step: FunctionStep
1487
+ ) => Promise<TOutput>;
1488
+
1489
+ /**
1490
+ * One declared parameter of a registered query.
1491
+ *
1492
+ * `caller: true` (or `type: "$caller"`) is the intent's IMMUTABLE binding:
1493
+ * the platform injects the invocation's user and refuses a call that supplies
1494
+ * the parameter itself.
1495
+ */
1496
+ export interface QueryParamSpec {
1497
+ type?: "string" | "number" | "boolean" | "any" | "$caller";
1498
+ caller?: boolean;
1499
+ optional?: boolean;
1500
+ default?: unknown;
1501
+ }
1502
+
1503
+ export interface QueryDefinition<TDb, TParams, TResult> {
1504
+ /** The models this query touches. Caching is off unless the run matches. */
1505
+ models: string[];
1506
+ params?: Record<string, QueryParamSpec>;
1507
+ /**
1508
+ * Cache the answer for `ttlMs` — capped by the platform, and applied ONLY
1509
+ * when the run is verified: every model the body touched was declared, and
1510
+ * no prepared operation was used. A write through the handle drops the
1511
+ * entries that read the written model.
1512
+ */
1513
+ cache?: { ttlMs: number };
1514
+ run: (db: TDb, params: TParams) => TResult | Promise<TResult>;
1515
+ }
1516
+
1517
+ /**
1518
+ * Register a named query over a database handle (#3187).
1519
+ *
1520
+ * A registration helper, not a language: `run` is ordinary code over the same
1521
+ * typed handle, and what registration adds is a name, declared parameters
1522
+ * (validated, coerced and defaulted), the `$caller` binding, and a cache the
1523
+ * platform may use when it can verify what the run touched.
1524
+ *
1525
+ * Register at MODULE scope: a registration made inside the handler still works
1526
+ * for direct calls but is invisible to `config push`'s manifest.
1527
+ */
1528
+ export declare function defineQuery<
1529
+ TDb = DatabaseHandle<any>,
1530
+ TParams = Record<string, any>,
1531
+ TResult = any
1532
+ >(
1533
+ name: string,
1534
+ definition: QueryDefinition<TDb, TParams, TResult>
1535
+ ): (db: TDb, params?: Record<string, unknown>) => Promise<TResult>;
1536
+
1537
+ /** The same, for a registration that writes. A mutation is never cached. */
1538
+ export declare function defineMutation<
1539
+ TDb = DatabaseHandle<any>,
1540
+ TParams = Record<string, any>,
1541
+ TResult = any
1542
+ >(
1543
+ name: string,
1544
+ definition: QueryDefinition<TDb, TParams, TResult>
1545
+ ): (db: TDb, params?: Record<string, unknown>) => Promise<TResult>;
1546
+
1547
+ /** The platform's cap on a registered query's cache TTL, in milliseconds. */
1548
+ export declare const MAX_QUERY_CACHE_TTL_MS: number;
1549
+
1550
+ /**
1551
+ * Map over items with BOUNDED concurrency (#3187). Results come back in the
1552
+ * input's order; the first rejection wins and nothing new is started after it.
1553
+ *
1554
+ * The bound matters inside a sandbox: an unbounded fan-out over a page of rows
1555
+ * spends the whole subrequest ceiling in one line.
1556
+ */
1557
+ export declare function pMap<T, R>(
1558
+ items: Iterable<T>,
1559
+ mapper: (item: T, index: number) => R | Promise<R>,
1560
+ options?: { concurrency?: number }
1561
+ ): Promise<R[]>;
1562
+
1563
+ /** The default concurrency `pMap` applies when none is given. */
1564
+ export declare const PMAP_DEFAULT_CONCURRENCY: number;
1565
+
1566
+ /**
1567
+ * A time-ordered ULID.
1568
+ *
1569
+ * GENERATE IT INSIDE `step.do`. A durable run re-executes its handler on
1570
+ * every resume and memoizes only what a step returned, so an id minted at the
1571
+ * top of a handler is a different id after a sleep — and whatever it was
1572
+ * written into is orphaned.
1573
+ */
1574
+ export declare function ulid(): string;
1575
+
1576
+ /** One family's durable `step.do` configuration. */
1577
+ export interface StepPolicy {
1578
+ retries: { limit: number; delay: string; backoff: string };
1579
+ timeout: string;
1580
+ }
1581
+
1582
+ /**
1583
+ * The per-family step policies the DSL runners use, generated from their own
1584
+ * timeout module (#3187):
1585
+ *
1586
+ * await step.do("send-receipt", stepPolicy.email, () =>
1587
+ * ctx.api.email.send({ body: { to, subject, htmlBody } }));
1588
+ *
1589
+ * `retries: 0` on email and the AI families is deliberate — a retried timeout
1590
+ * would send the same email twice or bill the same generation twice.
1591
+ */
1592
+ export declare const stepPolicy: {
1593
+ email: StepPolicy;
1594
+ llm: StepPolicy;
1595
+ gemini: StepPolicy;
1596
+ database: StepPolicy;
1597
+ };
701
1598
 
702
1599
  declare const _default: {
703
1600
  SDK_STUB_VERSION: string;
704
1601
  defineFunction: typeof defineFunction;
1602
+ defineQuery: typeof defineQuery;
1603
+ defineMutation: typeof defineMutation;
1604
+ pMap: typeof pMap;
1605
+ ulid: typeof ulid;
705
1606
  };
706
1607
  export default _default;
package/index.js CHANGED
@@ -31,4 +31,60 @@ export function defineFunction() {
31
31
  throw new Error(NOT_PROVIDED);
32
32
  }
33
33
 
34
- export default { SDK_STUB_VERSION, defineFunction };
34
+ /**
35
+ * The platform's cap on a registered query's cache TTL. The stub carries the
36
+ * value rather than throwing, because it is a constant an author may read at
37
+ * module scope while type-checking outside a sandbox.
38
+ */
39
+ export const MAX_QUERY_CACHE_TTL_MS = 60000;
40
+
41
+ /**
42
+ * Register a named query or mutation (#3187). Same reason as above: an ESM
43
+ * named import of an export a module does not have is a LINK error, so the
44
+ * stub must declare every export the platform copy has — and refuse.
45
+ */
46
+ export function defineQuery() {
47
+ throw new Error(NOT_PROVIDED);
48
+ }
49
+
50
+ export function defineMutation() {
51
+ throw new Error(NOT_PROVIDED);
52
+ }
53
+
54
+ /** Bounded-concurrency map. The platform copy implements it; this refuses. */
55
+ export function pMap() {
56
+ throw new Error(NOT_PROVIDED);
57
+ }
58
+
59
+ /** A time-ordered ULID, minted by the platform copy. */
60
+ export function ulid() {
61
+ throw new Error(NOT_PROVIDED);
62
+ }
63
+
64
+ /**
65
+ * The per-family durable step policies. The stub carries an empty shape rather
66
+ * than throwing: it is read at module scope by code that only type-checks.
67
+ */
68
+ export const PMAP_DEFAULT_CONCURRENCY = 8;
69
+
70
+ /**
71
+ * The per-family durable step policies. The stub carries the SHAPE and empty
72
+ * values: an author may read `stepPolicy.email` at module scope while
73
+ * type-checking outside a sandbox, and throwing there would break a build that
74
+ * never runs a function. The platform copy carries the runners' real numbers.
75
+ */
76
+ export const stepPolicy = {
77
+ email: null,
78
+ llm: null,
79
+ gemini: null,
80
+ database: null,
81
+ };
82
+
83
+ export default {
84
+ SDK_STUB_VERSION,
85
+ defineFunction,
86
+ defineQuery,
87
+ defineMutation,
88
+ pMap,
89
+ ulid,
90
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primitive-functions",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.2.0-alpha.1",
4
4
  "description": "The module a Primitive server function imports. Supplied by the platform at invoke time; reserved here so the name is ours before the runtime lands.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Primitive LLC",