primitive-functions 0.2.0-alpha.4 → 0.2.0-alpha.5
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.
- package/index.d.ts +375 -41
- package/index.js +5 -3
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -23,12 +23,41 @@ export interface FunctionUser {
|
|
|
23
23
|
email: string | null;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* What started this invocation. Narrow on `kind`.
|
|
28
|
+
*
|
|
29
|
+
* The same union the runtime builds (`src/server-functions/trigger-descriptor.ts`),
|
|
30
|
+
* held identical by `tests/api/spec/function-trigger-declarations-3281.test.ts`:
|
|
31
|
+
* a field the fire path sets is declared here, and nothing is declared here
|
|
32
|
+
* that the fire path does not set.
|
|
33
|
+
*/
|
|
27
34
|
export type FunctionTrigger =
|
|
35
|
+
/** An HTTP invocation: the caller is `ctx.user`. */
|
|
28
36
|
| { kind: "http" }
|
|
29
|
-
|
|
30
|
-
| {
|
|
31
|
-
|
|
37
|
+
/** A verified webhook delivery to the function's own key. */
|
|
38
|
+
| {
|
|
39
|
+
kind: "webhook";
|
|
40
|
+
/** The webhook key, which is the function key. */
|
|
41
|
+
webhookKey: string;
|
|
42
|
+
/** The platform's webhook row the delivery log lives under. */
|
|
43
|
+
webhookId: string;
|
|
44
|
+
/** The provider's event id (`X-Webhook-Event-Id`), when it sent one. */
|
|
45
|
+
externalEventId: string | null;
|
|
46
|
+
}
|
|
47
|
+
/** A cron entry firing, scheduled or from the `cron-triggers test` diagnostic. */
|
|
48
|
+
| {
|
|
49
|
+
kind: "cron";
|
|
50
|
+
/** The `[[function.triggers.cron]]` entry's `name`. */
|
|
51
|
+
name: string;
|
|
52
|
+
/** The platform's cron row. */
|
|
53
|
+
triggerId: string;
|
|
54
|
+
/** ISO 8601. The instant the fire was scheduled for; a diagnostic fire's is "now". */
|
|
55
|
+
scheduledFor: string;
|
|
56
|
+
/** Present, and true, only on the diagnostic fire: nothing was scheduled. */
|
|
57
|
+
manual?: true;
|
|
58
|
+
}
|
|
59
|
+
/** A write to a watched database type. */
|
|
60
|
+
| { kind: "database"; databaseId: string; databaseType: string }
|
|
32
61
|
/**
|
|
33
62
|
* A DSL workflow's `workflow.call` step reached this function (#3288).
|
|
34
63
|
*
|
|
@@ -37,7 +66,15 @@ export type FunctionTrigger =
|
|
|
37
66
|
* taking this variant with it. `workflowKey` names the PARENT workflow, and
|
|
38
67
|
* `runId`/`stepId` locate the step inside its run.
|
|
39
68
|
*/
|
|
40
|
-
| { kind: "workflow"; workflowKey: string; runId: string; stepId: string }
|
|
69
|
+
| { kind: "workflow"; workflowKey: string; runId: string; stepId: string }
|
|
70
|
+
/**
|
|
71
|
+
* Another function started this one with `ctx.functions.start` (#3280).
|
|
72
|
+
*
|
|
73
|
+
* `functionKey` names the PARENT, and `runId` its run — null when the
|
|
74
|
+
* parent was a request invocation over HTTP, which writes no run row, or a
|
|
75
|
+
* database-change fire, which writes none either.
|
|
76
|
+
*/
|
|
77
|
+
| { kind: "function"; functionKey: string; runId: string | null };
|
|
41
78
|
|
|
42
79
|
/** The result shape of an operation that answers in response headers. */
|
|
43
80
|
export interface HeaderResult {
|
|
@@ -57,7 +94,7 @@ export interface PrimitivePlatformError extends Error {
|
|
|
57
94
|
|
|
58
95
|
/**
|
|
59
96
|
* The typed HTTP profile, generated from the platform's OpenAPI document. Its
|
|
60
|
-
* namespaces mirror the operation ids: analytics, blobBuckets, channels, collections, configVars, connections, databaseTypeConfigs, databases, documents, email, functions, gemini, groups, integrations,
|
|
97
|
+
* namespaces mirror the operation ids: analytics, blobBuckets, channels, collections, configVars, connections, databaseTypeConfigs, databases, documents, email, functions, gemini, groups, integrations, llm, locks, notifications, prompts, resourceMetadata, secrets, users.
|
|
61
98
|
* Methods take one options object carrying the operation's path parameters,
|
|
62
99
|
* query parameters, request headers (under their wire names) and `body`.
|
|
63
100
|
*
|
|
@@ -65,11 +102,13 @@ export interface PrimitivePlatformError extends Error {
|
|
|
65
102
|
* type-checks is a method the platform publishes — and a missing path
|
|
66
103
|
* parameter or a missing required header is a compile error rather than a
|
|
67
104
|
* `TypeError` at invoke time. Every call runs with the app's own SYSTEM
|
|
68
|
-
* authority (#3279): the invocation gate was the authorization. The
|
|
69
|
-
* namespaces the gateway does not admit
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
105
|
+
* authority (#3279): the invocation gate was the authorization. The two
|
|
106
|
+
* namespaces the gateway does not admit are still declared: they exist, they
|
|
107
|
+
* answer the gateway's structured denial, and hiding them would make a route's
|
|
108
|
+
* availability look like a typo. Those are `databaseTypeConfigs` whole, and
|
|
109
|
+
* `functions` except for `functions.start` — the nested-start door #3280
|
|
110
|
+
* admits by name, which `ctx.functions.start` calls. `functions.invoke`
|
|
111
|
+
* stays refused: same-run composition is an import.
|
|
73
112
|
*/
|
|
74
113
|
export interface FunctionApi {
|
|
75
114
|
"analytics": {
|
|
@@ -145,6 +184,10 @@ export interface FunctionApi {
|
|
|
145
184
|
"searchUsers"(args?: {
|
|
146
185
|
"q"?: string | number | boolean;
|
|
147
186
|
"limit"?: string | number | boolean;
|
|
187
|
+
"signupDay"?: string | number | boolean;
|
|
188
|
+
"signupStartDay"?: string | number | boolean;
|
|
189
|
+
"signupEndDay"?: string | number | boolean;
|
|
190
|
+
"offset"?: string | number | boolean;
|
|
148
191
|
"current_timestamp"?: string | number | boolean;
|
|
149
192
|
"_bust"?: string | number | boolean;
|
|
150
193
|
}): Promise<any>;
|
|
@@ -600,7 +643,7 @@ export interface FunctionApi {
|
|
|
600
643
|
"query"(args: {
|
|
601
644
|
"databaseId": string | number;
|
|
602
645
|
body: unknown;
|
|
603
|
-
}): Promise<any>;
|
|
646
|
+
}): Promise<{ items: any[]; hasMore: boolean; nextCursor?: string; prevCursor?: string }>;
|
|
604
647
|
/** `databases.records.registerIndex` — POST /databases/{databaseId}/records/index/register. Database records: index/register (requires manager-or-higher on the database, or an app-admin/owner role) */
|
|
605
648
|
"registerIndex"(args: {
|
|
606
649
|
"databaseId": string | number;
|
|
@@ -968,11 +1011,22 @@ export interface FunctionApi {
|
|
|
968
1011
|
}): Promise<any>;
|
|
969
1012
|
};
|
|
970
1013
|
"functions": {
|
|
971
|
-
/** `functions.invoke` — POST /functions/{functionKey}. Invoke a server function: a
|
|
1014
|
+
/** `functions.invoke` — POST /functions/{functionKey}. Invoke a server function: a request function returns its result, a task function starts a run */
|
|
972
1015
|
"invoke"(args: {
|
|
973
1016
|
"functionKey": string | number;
|
|
974
1017
|
body?: unknown;
|
|
975
1018
|
}): Promise<any>;
|
|
1019
|
+
/** `functions.logs` — GET /functions/{functionKey}/logs. List a server function's invocation logs, newest first */
|
|
1020
|
+
"logs"(args: {
|
|
1021
|
+
"functionKey": string | number;
|
|
1022
|
+
"limit"?: string | number | boolean;
|
|
1023
|
+
"cursor"?: string | number | boolean;
|
|
1024
|
+
}): Promise<any>;
|
|
1025
|
+
/** `functions.start` — POST /functions/{functionKey}/start. Start a task function from inside another server function */
|
|
1026
|
+
"start"(args: {
|
|
1027
|
+
"functionKey": string | number;
|
|
1028
|
+
body?: unknown;
|
|
1029
|
+
}): Promise<any>;
|
|
976
1030
|
};
|
|
977
1031
|
"gemini": {
|
|
978
1032
|
/** `gemini.countTokens` — POST /gemini/count-tokens. Count tokens for a Gemini request */
|
|
@@ -1080,18 +1134,6 @@ export interface FunctionApi {
|
|
|
1080
1134
|
"integrationKey": string | number;
|
|
1081
1135
|
}): Promise<any>;
|
|
1082
1136
|
};
|
|
1083
|
-
"iterations": {
|
|
1084
|
-
/** `iterations.get` — GET /iterations/{iterationName}. Get details for a single iteration */
|
|
1085
|
-
"get"(args: {
|
|
1086
|
-
"iterationName": string | number;
|
|
1087
|
-
}): Promise<any>;
|
|
1088
|
-
/** `iterations.list` — GET /iterations. List iteration runs */
|
|
1089
|
-
"list"(args?: Record<string, never>): Promise<any>;
|
|
1090
|
-
/** `iterations.reset` — POST /iterations/{iterationName}/reset. Reset a terminal iteration so the next trigger runs fresh */
|
|
1091
|
-
"reset"(args: {
|
|
1092
|
-
"iterationName": string | number;
|
|
1093
|
-
}): Promise<any>;
|
|
1094
|
-
};
|
|
1095
1137
|
"llm": {
|
|
1096
1138
|
/** `llm.chat` — POST /llm/chat. Run an LLM chat completion */
|
|
1097
1139
|
"chat"(args: {
|
|
@@ -1267,6 +1309,46 @@ export type DatabaseModels<K extends string> = K extends keyof DatabaseSchemas
|
|
|
1267
1309
|
? DatabaseSchemas[K]
|
|
1268
1310
|
: Record<string, Record<string, unknown>>;
|
|
1269
1311
|
|
|
1312
|
+
/**
|
|
1313
|
+
* The app's functions, key by key — EMPTY here and filled by the declaration
|
|
1314
|
+
* `primitive config push` writes into the config tree's `functions/`
|
|
1315
|
+
* directory (`primitive-function-types.d.ts`): each key's declared input and
|
|
1316
|
+
* output types (from its `inputSchema` and `outputSchema`) and its mode. It
|
|
1317
|
+
* is what types `defineFunction("<key>", handler)`.
|
|
1318
|
+
*/
|
|
1319
|
+
export interface FunctionSchemas {}
|
|
1320
|
+
|
|
1321
|
+
/**
|
|
1322
|
+
* The keys `defineFunction(key, handler)` accepts: every key the augmentation
|
|
1323
|
+
* declares once a tree has pushed, so a key the tree does not declare is a
|
|
1324
|
+
* compile error — and `string` before that, the `DatabaseTypeKeys` rule, so an
|
|
1325
|
+
* unaugmented tree keeps compiling.
|
|
1326
|
+
*/
|
|
1327
|
+
export type FunctionKeys = [keyof FunctionSchemas] extends [never]
|
|
1328
|
+
? string
|
|
1329
|
+
: keyof FunctionSchemas & string;
|
|
1330
|
+
|
|
1331
|
+
/** A declared function's input type, or `any` when nothing is declared. */
|
|
1332
|
+
export type FunctionInput<K extends string> = K extends keyof FunctionSchemas
|
|
1333
|
+
? FunctionSchemas[K] extends { input: infer I }
|
|
1334
|
+
? I
|
|
1335
|
+
: any
|
|
1336
|
+
: any;
|
|
1337
|
+
|
|
1338
|
+
/** A declared function's output type, or `any` when nothing is declared. */
|
|
1339
|
+
export type FunctionOutput<K extends string> = K extends keyof FunctionSchemas
|
|
1340
|
+
? FunctionSchemas[K] extends { output: infer O }
|
|
1341
|
+
? O
|
|
1342
|
+
: any
|
|
1343
|
+
: any;
|
|
1344
|
+
|
|
1345
|
+
/** A declared function's mode, fixed at generation time. */
|
|
1346
|
+
export type FunctionMode<K extends string> = K extends keyof FunctionSchemas
|
|
1347
|
+
? FunctionSchemas[K] extends { mode: infer M }
|
|
1348
|
+
? M
|
|
1349
|
+
: "request" | "task"
|
|
1350
|
+
: "request" | "task";
|
|
1351
|
+
|
|
1270
1352
|
/**
|
|
1271
1353
|
* The model names one database type addresses — its own, or any name at all
|
|
1272
1354
|
* for a type that declares no schema (the DO is schemaless, so a grant on such
|
|
@@ -1311,7 +1393,14 @@ export type ModelBatchOperation<TRow> = {
|
|
|
1311
1393
|
};
|
|
1312
1394
|
|
|
1313
1395
|
export interface DatabaseModelHandle<TRow> {
|
|
1314
|
-
|
|
1396
|
+
/**
|
|
1397
|
+
* One page of this model's rows, in the decided envelope — `{ items,
|
|
1398
|
+
* hasMore, nextCursor? }` (#3287), the same shape `ctx.doc(...)`,
|
|
1399
|
+
* `ctx.users.list` and the client library answer. The route's own wire
|
|
1400
|
+
* shape is unchanged; the SDK is where the one name lives, so shared paging
|
|
1401
|
+
* code can be written once.
|
|
1402
|
+
*/
|
|
1403
|
+
query(body?: ModelScopedBody): Promise<{ items: TRow[]; hasMore: boolean; nextCursor?: string }>;
|
|
1315
1404
|
count(body?: ModelScopedBody): Promise<any>;
|
|
1316
1405
|
aggregate(body: ModelScopedBody): Promise<any>;
|
|
1317
1406
|
save(body: ModelScopedBody<{ id?: string; data: Partial<TRow>; [key: string]: unknown }>): Promise<any>;
|
|
@@ -1343,6 +1432,50 @@ export interface DatabaseHandle<TModels> {
|
|
|
1343
1432
|
runOperation(name: string, params?: Record<string, unknown>): Promise<any>;
|
|
1344
1433
|
}
|
|
1345
1434
|
|
|
1435
|
+
/**
|
|
1436
|
+
* The app's DOCUMENT models — EMPTY here and filled by the declaration
|
|
1437
|
+
* `primitive config push` writes into the config tree's `functions/` directory
|
|
1438
|
+
* (`primitive-document-types.d.ts`, from the project's `models/models.toml`).
|
|
1439
|
+
* A project with no document schema gets the open form and still compiles.
|
|
1440
|
+
*/
|
|
1441
|
+
export interface DocumentSchemas {}
|
|
1442
|
+
|
|
1443
|
+
/** The model names `ctx.doc(id).model()` accepts — every declared one, or `string` before a push. */
|
|
1444
|
+
export type DocumentModelNames = [keyof DocumentSchemas] extends [never]
|
|
1445
|
+
? string
|
|
1446
|
+
: keyof DocumentSchemas & string;
|
|
1447
|
+
|
|
1448
|
+
/** A document model's row shape, or an open record for an undeclared schema. */
|
|
1449
|
+
export type DocumentModelRow<M extends string> = M extends keyof DocumentSchemas
|
|
1450
|
+
? DocumentSchemas[M]
|
|
1451
|
+
: Record<string, unknown>;
|
|
1452
|
+
|
|
1453
|
+
/** The options a document model read takes: a filter object (or its JSON), a page size, a cursor. */
|
|
1454
|
+
export interface DocumentQueryOptions {
|
|
1455
|
+
filter?: Record<string, unknown> | string;
|
|
1456
|
+
limit?: number;
|
|
1457
|
+
cursor?: string;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
/**
|
|
1461
|
+
* One document model, bound to its document and its model name — a thin
|
|
1462
|
+
* binding over `ctx.api.documents.records.*` with the route's own shapes.
|
|
1463
|
+
*/
|
|
1464
|
+
export interface DocumentModelHandle<TRow> {
|
|
1465
|
+
query(options?: DocumentQueryOptions): Promise<{ items: TRow[]; hasMore: boolean; nextCursor?: string }>;
|
|
1466
|
+
count(options?: { filter?: Record<string, unknown> | string }): Promise<{ count: number }>;
|
|
1467
|
+
aggregate(body: Record<string, unknown>): Promise<any>;
|
|
1468
|
+
save(body: { id: string; data: Partial<TRow>; options?: Record<string, unknown> }): Promise<{ record: TRow }>;
|
|
1469
|
+
patch(recordId: string, body: { data: Partial<TRow>; options?: Record<string, unknown> }): Promise<{ record: TRow }>;
|
|
1470
|
+
delete(recordId: string): Promise<{ deleted: boolean }>;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/** A document, addressed once; its models are typed from `DocumentSchemas`. */
|
|
1474
|
+
export interface DocumentHandle {
|
|
1475
|
+
documentId: string;
|
|
1476
|
+
model<M extends DocumentModelNames>(modelName: M): DocumentModelHandle<DocumentModelRow<M>>;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1346
1479
|
/**
|
|
1347
1480
|
* One call through a granted integration — #3183.
|
|
1348
1481
|
*
|
|
@@ -1421,6 +1554,67 @@ export interface ChannelGrantResult {
|
|
|
1421
1554
|
expiresAt: number;
|
|
1422
1555
|
}
|
|
1423
1556
|
|
|
1557
|
+
/** Where to start and how big a page to take — #3280. */
|
|
1558
|
+
export interface UserPageOptions {
|
|
1559
|
+
/** Page size. Capped by the route at 100. */
|
|
1560
|
+
limit?: number;
|
|
1561
|
+
/** The `nextCursor` of the page before this one. */
|
|
1562
|
+
cursor?: string;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
/** One user on the roster, as the platform's own users route reports them. */
|
|
1566
|
+
export interface UserPageItem {
|
|
1567
|
+
userId: string;
|
|
1568
|
+
email: string | null;
|
|
1569
|
+
name: string | null;
|
|
1570
|
+
avatarUrl: string | null;
|
|
1571
|
+
role: string;
|
|
1572
|
+
addedAt: string | null;
|
|
1573
|
+
status: string;
|
|
1574
|
+
disabledAt: string | null;
|
|
1575
|
+
[key: string]: unknown;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
/** The decided paged envelope, the same shape every paged read answers. */
|
|
1579
|
+
export interface UserPage {
|
|
1580
|
+
items: UserPageItem[];
|
|
1581
|
+
hasMore: boolean;
|
|
1582
|
+
/** Absent on the last page. */
|
|
1583
|
+
nextCursor?: string;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
/** How a nested start is keyed and labelled — #3280. */
|
|
1587
|
+
export interface FunctionStartOptions {
|
|
1588
|
+
/**
|
|
1589
|
+
* Idempotency key, scoped to the tree's root initiator and the resolved
|
|
1590
|
+
* context document: a repeat replays the run that already exists rather than
|
|
1591
|
+
* starting a second. At most 100 characters.
|
|
1592
|
+
*/
|
|
1593
|
+
runKey?: string;
|
|
1594
|
+
/**
|
|
1595
|
+
* The document the child's run is keyed under. Defaults through the
|
|
1596
|
+
* inheritance rule: the parent run's context, else the root caller's root
|
|
1597
|
+
* document, else `fn:<the root function's id>`. At most 100 characters.
|
|
1598
|
+
*/
|
|
1599
|
+
contextDocId?: string;
|
|
1600
|
+
/** Caller metadata, at most 1 KB encoded. */
|
|
1601
|
+
meta?: Record<string, unknown>;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
/** The start envelope, the same one a workflow start answers with — #3280. */
|
|
1605
|
+
export interface FunctionStartResult {
|
|
1606
|
+
/** Poll this on the platform's run-status route. */
|
|
1607
|
+
runId: string;
|
|
1608
|
+
runKey: string;
|
|
1609
|
+
instanceId: string;
|
|
1610
|
+
status: string;
|
|
1611
|
+
/**
|
|
1612
|
+
* True when `runKey` already named a run in this tree, which this envelope
|
|
1613
|
+
* describes. That is what makes a run key a singleton.
|
|
1614
|
+
*/
|
|
1615
|
+
existing?: boolean;
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1424
1618
|
export interface FunctionContext {
|
|
1425
1619
|
/** The HTTP caller, or null for a webhook, cron or database-change fire. */
|
|
1426
1620
|
user: FunctionUser | null;
|
|
@@ -1435,6 +1629,13 @@ export interface FunctionContext {
|
|
|
1435
1629
|
databaseId: string,
|
|
1436
1630
|
databaseType: K
|
|
1437
1631
|
): DatabaseHandle<DatabaseModels<K>>;
|
|
1632
|
+
/**
|
|
1633
|
+
* A typed handle over one document's record models, typed from the
|
|
1634
|
+
* project's `models/models.toml` — `ctx.db`'s shape for documents. It
|
|
1635
|
+
* confers nothing: every call is a `documents.records.*` operation on the
|
|
1636
|
+
* same authority.
|
|
1637
|
+
*/
|
|
1638
|
+
doc(documentId: string): DocumentHandle;
|
|
1438
1639
|
/**
|
|
1439
1640
|
* Outbound HTTP, through a granted integration and nowhere else (#3183).
|
|
1440
1641
|
*
|
|
@@ -1451,6 +1652,26 @@ export interface FunctionContext {
|
|
|
1451
1652
|
request?: IntegrationCallRequest
|
|
1452
1653
|
): Promise<IntegrationCallResult>;
|
|
1453
1654
|
};
|
|
1655
|
+
/**
|
|
1656
|
+
* Start a TASK function from inside this one — #3280.
|
|
1657
|
+
*
|
|
1658
|
+
* The one nested door, and it is a START. A request function is code and
|
|
1659
|
+
* code composes by being IMPORTED, so there is no synchronous nested
|
|
1660
|
+
* invocation to reach for; a request-mode callee answers
|
|
1661
|
+
* `FUNCTION_MODE_MISMATCH`.
|
|
1662
|
+
*
|
|
1663
|
+
* The callee's `access` gate is not consulted — this function's own gate was
|
|
1664
|
+
* the authorization — and every run in the tree is keyed by whoever started
|
|
1665
|
+
* it, so the member who invoked the root polls and terminates them all.
|
|
1666
|
+
* Nesting is bounded at four levels.
|
|
1667
|
+
*/
|
|
1668
|
+
functions: {
|
|
1669
|
+
start(
|
|
1670
|
+
functionKey: string,
|
|
1671
|
+
input?: unknown,
|
|
1672
|
+
options?: FunctionStartOptions
|
|
1673
|
+
): Promise<FunctionStartResult>;
|
|
1674
|
+
};
|
|
1454
1675
|
/**
|
|
1455
1676
|
* Run one of the app's prompts, under a `prompt:<key>` grant (#3183).
|
|
1456
1677
|
*
|
|
@@ -1485,6 +1706,24 @@ export interface FunctionContext {
|
|
|
1485
1706
|
* error.
|
|
1486
1707
|
*/
|
|
1487
1708
|
users: {
|
|
1709
|
+
/**
|
|
1710
|
+
* One page of the app's users — #3280.
|
|
1711
|
+
*
|
|
1712
|
+
* On the APP's system authority, whoever invoked the function: a member
|
|
1713
|
+
* who passes this function's gate reads whatever roster it chooses to
|
|
1714
|
+
* expose, so say who may in the function's own `access` expression.
|
|
1715
|
+
* `limit` is capped by the route at 100.
|
|
1716
|
+
*/
|
|
1717
|
+
list(options?: UserPageOptions): Promise<UserPage>;
|
|
1718
|
+
/**
|
|
1719
|
+
* Every page of the app's users, in order — #3280.
|
|
1720
|
+
*
|
|
1721
|
+
* FOR A REQUEST FUNCTION AND A SINGLE-SLICE LOOP. A durable loop must take
|
|
1722
|
+
* its pages inside `step.do` with an EXPLICIT cursor: a memoized step does
|
|
1723
|
+
* not advance an iterator on resume, so an iteration across a sleep would
|
|
1724
|
+
* replay pages it had already taken.
|
|
1725
|
+
*/
|
|
1726
|
+
iterate(options?: UserPageOptions): AsyncIterable<UserPage>;
|
|
1488
1727
|
send(userId: string, payload: unknown): Promise<SendResult>;
|
|
1489
1728
|
};
|
|
1490
1729
|
/** The same frame to ONE connection, under a `connections:send` grant. */
|
|
@@ -1537,29 +1776,49 @@ export interface FunctionStep {
|
|
|
1537
1776
|
export declare const SDK_STUB_VERSION: string;
|
|
1538
1777
|
|
|
1539
1778
|
/**
|
|
1540
|
-
*
|
|
1541
|
-
*
|
|
1542
|
-
* Both authoring styles reach the platform bootstrap identically — a plain
|
|
1543
|
-
* default export taking `(input, ctx, step)` runs exactly as a wrapped one
|
|
1544
|
-
* does — so this is a typing and intent marker, not a different calling
|
|
1545
|
-
* convention.
|
|
1779
|
+
* The handler a function exports, typed for one declared key.
|
|
1546
1780
|
*
|
|
1547
|
-
* `step` is the third argument in BOTH modes (#3186). A
|
|
1548
|
-
* engine's live `WorkflowStep`; a
|
|
1781
|
+
* `step` is the third argument in BOTH modes (#3186). A task run gets the
|
|
1782
|
+
* engine's live `WorkflowStep`; a request invocation gets a passthrough shim
|
|
1549
1783
|
* (`do` runs the body, `sleep` resolves at once, `waitForEvent` throws a
|
|
1550
|
-
* named error), so a
|
|
1784
|
+
* named error), so a task-authored body can be exercised as a request.
|
|
1551
1785
|
*/
|
|
1786
|
+
export type FunctionHandler<TInput, TOutput> = (
|
|
1787
|
+
input: TInput,
|
|
1788
|
+
ctx: FunctionContext,
|
|
1789
|
+
step: FunctionStep
|
|
1790
|
+
) => Promise<TOutput>;
|
|
1791
|
+
|
|
1792
|
+
/**
|
|
1793
|
+
* Declare a server function's handler, typed from its declaration.
|
|
1794
|
+
*
|
|
1795
|
+
* The KEYED form, `defineFunction("<key>", handler)`, is typed from the
|
|
1796
|
+
* `FunctionSchemas` augmentation `primitive config push` writes beside the
|
|
1797
|
+
* sources: `input` is the key's declared input, the return is checked against
|
|
1798
|
+
* its declared output, and a key the tree does not declare is a compile error.
|
|
1799
|
+
* `config push` also refuses an entry whose key names another file's. In a
|
|
1800
|
+
* tree that has not pushed yet the key is any string and both types are `any`.
|
|
1801
|
+
*
|
|
1802
|
+
* The UNKEYED form is what it always was: author-declared generics. Both
|
|
1803
|
+
* styles reach the platform bootstrap identically — a plain default export
|
|
1804
|
+
* taking `(input, ctx, step)` runs exactly as a wrapped one does — so this is
|
|
1805
|
+
* a typing and intent marker, not a different calling convention.
|
|
1806
|
+
*/
|
|
1807
|
+
export declare function defineFunction<K extends FunctionKeys>(
|
|
1808
|
+
key: K,
|
|
1809
|
+
handler: (
|
|
1810
|
+
input: FunctionInput<K>,
|
|
1811
|
+
ctx: FunctionContext,
|
|
1812
|
+
step: FunctionStep
|
|
1813
|
+
) => FunctionOutput<K> | Promise<FunctionOutput<K>>
|
|
1814
|
+
): FunctionHandler<FunctionInput<K>, FunctionOutput<K>> & { functionKey: K };
|
|
1552
1815
|
export declare function defineFunction<TInput = unknown, TOutput = unknown>(
|
|
1553
1816
|
handler: (
|
|
1554
1817
|
input: TInput,
|
|
1555
1818
|
ctx: FunctionContext,
|
|
1556
1819
|
step: FunctionStep
|
|
1557
1820
|
) => TOutput | Promise<TOutput>
|
|
1558
|
-
):
|
|
1559
|
-
input: TInput,
|
|
1560
|
-
ctx: FunctionContext,
|
|
1561
|
-
step: FunctionStep
|
|
1562
|
-
) => Promise<TOutput>;
|
|
1821
|
+
): FunctionHandler<TInput, TOutput>;
|
|
1563
1822
|
|
|
1564
1823
|
/**
|
|
1565
1824
|
* One declared parameter of a registered query.
|
|
@@ -1568,13 +1827,64 @@ export declare function defineFunction<TInput = unknown, TOutput = unknown>(
|
|
|
1568
1827
|
* the platform injects the invocation's user and refuses a call that supplies
|
|
1569
1828
|
* the parameter itself.
|
|
1570
1829
|
*/
|
|
1830
|
+
/** The scalar parameter types, and an array parameter's element types. */
|
|
1831
|
+
export type QueryScalarParamType = "string" | "number" | "boolean" | "any";
|
|
1832
|
+
|
|
1571
1833
|
export interface QueryParamSpec {
|
|
1572
|
-
type?:
|
|
1834
|
+
type?: QueryScalarParamType | "$caller" | "array";
|
|
1835
|
+
/** For `type: "array"` — the element type; absent means any element. */
|
|
1836
|
+
items?: { type: QueryScalarParamType };
|
|
1573
1837
|
caller?: boolean;
|
|
1574
1838
|
optional?: boolean;
|
|
1575
1839
|
default?: unknown;
|
|
1576
1840
|
}
|
|
1577
1841
|
|
|
1842
|
+
/** A scalar parameter type's TypeScript type. */
|
|
1843
|
+
export type QueryScalarValue<T> = T extends "string"
|
|
1844
|
+
? string
|
|
1845
|
+
: T extends "number"
|
|
1846
|
+
? number
|
|
1847
|
+
: T extends "boolean"
|
|
1848
|
+
? boolean
|
|
1849
|
+
: T extends "$caller"
|
|
1850
|
+
? string
|
|
1851
|
+
: any;
|
|
1852
|
+
|
|
1853
|
+
/** The value `run` receives for one declared parameter. */
|
|
1854
|
+
export type QueryParamValue<S> = S extends { caller: true }
|
|
1855
|
+
? string
|
|
1856
|
+
: S extends { type: "array"; items: { type: infer I } }
|
|
1857
|
+
? QueryScalarValue<I>[]
|
|
1858
|
+
: S extends { type: "array" }
|
|
1859
|
+
? unknown[]
|
|
1860
|
+
: S extends { type: infer T }
|
|
1861
|
+
? QueryScalarValue<T>
|
|
1862
|
+
: any;
|
|
1863
|
+
|
|
1864
|
+
type QueryOptionalKeys<P> = {
|
|
1865
|
+
[K in keyof P]: P[K] extends { optional: true } ? K : never;
|
|
1866
|
+
}[keyof P];
|
|
1867
|
+
|
|
1868
|
+
/**
|
|
1869
|
+
* `run`'s `params`, typed from the declaration: scalars as their scalar,
|
|
1870
|
+
* `$caller` as a string, an array as `T[]`, an `optional: true` parameter
|
|
1871
|
+
* as an optional key (a parameter with a default is always present). An
|
|
1872
|
+
* undeclared name is a compile error.
|
|
1873
|
+
*/
|
|
1874
|
+
export type QueryParams<P> = {
|
|
1875
|
+
[K in Exclude<keyof P, QueryOptionalKeys<P>>]: QueryParamValue<P[K]>;
|
|
1876
|
+
} & {
|
|
1877
|
+
[K in QueryOptionalKeys<P>]?: QueryParamValue<P[K]>;
|
|
1878
|
+
};
|
|
1879
|
+
|
|
1880
|
+
/** A registration's definition with its parameters DECLARED, so `run` is typed from them. */
|
|
1881
|
+
export interface TypedQueryDefinition<TDb, TSpec extends Record<string, QueryParamSpec>, TResult> {
|
|
1882
|
+
models: string[];
|
|
1883
|
+
params?: TSpec;
|
|
1884
|
+
cache?: { ttlMs: number };
|
|
1885
|
+
run: (db: TDb, params: QueryParams<TSpec>) => TResult | Promise<TResult>;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1578
1888
|
export interface QueryDefinition<TDb, TParams, TResult> {
|
|
1579
1889
|
/** The models this query touches. Caching is off unless the run matches. */
|
|
1580
1890
|
models: string[];
|
|
@@ -1599,7 +1909,23 @@ export interface QueryDefinition<TDb, TParams, TResult> {
|
|
|
1599
1909
|
*
|
|
1600
1910
|
* Register at MODULE scope: a registration made inside the handler still works
|
|
1601
1911
|
* for direct calls but is invisible to `config push`'s manifest.
|
|
1912
|
+
*
|
|
1913
|
+
* `run`'s `params` are TYPED from the declaration (the first overload,
|
|
1914
|
+
* inferred with a `const` type parameter): a scalar as its scalar, `$caller`
|
|
1915
|
+
* as a string, `{ type: "array", items: { type: "string" } }` as `string[]`,
|
|
1916
|
+
* an `optional: true` parameter as an optional key; an undeclared name inside
|
|
1917
|
+
* `run` is a compile error. A declared default is coerced to the declared
|
|
1918
|
+
* type at registration, so `run` receives what the declaration promises. The
|
|
1919
|
+
* second overload keeps an explicit `TParams`.
|
|
1602
1920
|
*/
|
|
1921
|
+
export declare function defineQuery<
|
|
1922
|
+
const TSpec extends Record<string, QueryParamSpec>,
|
|
1923
|
+
TDb = DatabaseHandle<any>,
|
|
1924
|
+
TResult = any
|
|
1925
|
+
>(
|
|
1926
|
+
name: string,
|
|
1927
|
+
definition: TypedQueryDefinition<TDb, TSpec, TResult>
|
|
1928
|
+
): (db: TDb, params?: Record<string, unknown>) => Promise<TResult>;
|
|
1603
1929
|
export declare function defineQuery<
|
|
1604
1930
|
TDb = DatabaseHandle<any>,
|
|
1605
1931
|
TParams = Record<string, any>,
|
|
@@ -1610,6 +1936,14 @@ export declare function defineQuery<
|
|
|
1610
1936
|
): (db: TDb, params?: Record<string, unknown>) => Promise<TResult>;
|
|
1611
1937
|
|
|
1612
1938
|
/** The same, for a registration that writes. A mutation is never cached. */
|
|
1939
|
+
export declare function defineMutation<
|
|
1940
|
+
const TSpec extends Record<string, QueryParamSpec>,
|
|
1941
|
+
TDb = DatabaseHandle<any>,
|
|
1942
|
+
TResult = any
|
|
1943
|
+
>(
|
|
1944
|
+
name: string,
|
|
1945
|
+
definition: TypedQueryDefinition<TDb, TSpec, TResult>
|
|
1946
|
+
): (db: TDb, params?: Record<string, unknown>) => Promise<TResult>;
|
|
1613
1947
|
export declare function defineMutation<
|
|
1614
1948
|
TDb = DatabaseHandle<any>,
|
|
1615
1949
|
TParams = Record<string, any>,
|
package/index.js
CHANGED
|
@@ -24,10 +24,12 @@ const NOT_PROVIDED =
|
|
|
24
24
|
export const SDK_STUB_VERSION = "0.0.1";
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* Declare a function's handler
|
|
28
|
-
*
|
|
27
|
+
* Declare a function's handler — `defineFunction(handler)` or the keyed
|
|
28
|
+
* `defineFunction("<key>", handler)`. The platform copy returns the handler
|
|
29
|
+
* wrapped with its invocation context; this one refuses, loudly, whichever
|
|
30
|
+
* shape it is called with.
|
|
29
31
|
*/
|
|
30
|
-
export function defineFunction() {
|
|
32
|
+
export function defineFunction(_keyOrHandler, _maybeHandler) {
|
|
31
33
|
throw new Error(NOT_PROVIDED);
|
|
32
34
|
}
|
|
33
35
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primitive-functions",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.5",
|
|
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",
|