@xanots/sdk 0.0.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.
- package/LICENSE +21 -0
- package/README.md +384 -0
- package/dist/agent-file-refresh-7XCACU34.js +95 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +184 -0
- package/dist/capture-HUV5BNTC.js +32 -0
- package/dist/chunk-26CNBZE2.js +963 -0
- package/dist/chunk-33ND6LKO.js +78 -0
- package/dist/chunk-3DUAGYGP.js +1550 -0
- package/dist/chunk-3IGNIP6R.js +89 -0
- package/dist/chunk-47WDWMBJ.js +14 -0
- package/dist/chunk-4BXJGVZ3.js +318 -0
- package/dist/chunk-4HT3BNZ7.js +675 -0
- package/dist/chunk-4YMD2OOZ.js +23 -0
- package/dist/chunk-5WGEURVI.js +156 -0
- package/dist/chunk-5YTBTF25.js +29 -0
- package/dist/chunk-6DHBYBTO.js +166 -0
- package/dist/chunk-76QBEIGO.js +66 -0
- package/dist/chunk-7DKX2SPN.js +100 -0
- package/dist/chunk-7REDODS2.js +468 -0
- package/dist/chunk-C56BC2FY.js +254 -0
- package/dist/chunk-DGSF2Q5H.js +60 -0
- package/dist/chunk-EMCAWMHC.js +3982 -0
- package/dist/chunk-EZG76F7R.js +159 -0
- package/dist/chunk-FJ6ZS5KB.js +3607 -0
- package/dist/chunk-GNPVYOPB.js +17 -0
- package/dist/chunk-HJPTWBLH.js +38 -0
- package/dist/chunk-IZW6MK3U.js +248 -0
- package/dist/chunk-LH6Z6KFV.js +247 -0
- package/dist/chunk-MZUI3JNX.js +93 -0
- package/dist/chunk-NDZFBZHC.js +167 -0
- package/dist/chunk-NOO35BQ2.js +37 -0
- package/dist/chunk-NUQCEOKA.js +13 -0
- package/dist/chunk-QTNO2WD6.js +56 -0
- package/dist/chunk-RVB7ITKN.js +49 -0
- package/dist/chunk-TRU5OHQ5.js +6904 -0
- package/dist/chunk-VKFQJEMW.js +814 -0
- package/dist/chunk-VTIL47DT.js +125 -0
- package/dist/chunk-WHOJWOSV.js +112 -0
- package/dist/chunk-WKP4D5MO.js +1692 -0
- package/dist/chunk-X4DVXBFY.js +38 -0
- package/dist/chunk-XQ22GLYS.js +118 -0
- package/dist/chunk-YDZYMZBE.js +670 -0
- package/dist/chunk-YGPIY3WT.js +1146 -0
- package/dist/chunk-YYRDLFSJ.js +602 -0
- package/dist/chunk-ZUTSMMAG.js +46 -0
- package/dist/cli.d.ts +331 -0
- package/dist/cli.js +33 -0
- package/dist/codegen-command-OOKK6AZK.js +40 -0
- package/dist/codegen.d.ts +114 -0
- package/dist/codegen.js +71 -0
- package/dist/completion-TIPPZN7H.js +298 -0
- package/dist/config-NL33PN4D.js +84 -0
- package/dist/deploy-command-4EQ7XX5G.js +451 -0
- package/dist/env-target-IFJ5QDHC.js +16 -0
- package/dist/ephemeral-command-3X3I4ULC.js +242 -0
- package/dist/index.d.ts +4477 -0
- package/dist/index.js +300 -0
- package/dist/init-command-R6H7ZXW5.js +27 -0
- package/dist/internal.d.ts +74 -0
- package/dist/internal.js +2065 -0
- package/dist/io-AMIKRLPC.js +11 -0
- package/dist/live-diff-Y3AKETHE.js +196 -0
- package/dist/lock-3CVKALKT.js +37 -0
- package/dist/lock-commands-XTR2YKLY.js +232 -0
- package/dist/login-command-ACJF6KWQ.js +167 -0
- package/dist/logout-command-MX3MJS5U.js +68 -0
- package/dist/loop-OM3P2Z6O.js +93 -0
- package/dist/marketplace-command-RATXTKXN.js +379 -0
- package/dist/meta-client-OW5WKWW7.js +170 -0
- package/dist/node.d.ts +59 -0
- package/dist/node.js +442 -0
- package/dist/profile-command-SWJ3SPKR.js +77 -0
- package/dist/release-command-VV5UVZKL.js +427 -0
- package/dist/response-CVAE2kMj.d.ts +1915 -0
- package/dist/routes-manifest-SP3ZXLMR.js +244 -0
- package/dist/runtime-V4C3AC3A.js +13 -0
- package/dist/sandbox-details-command-HJE5SPVG.js +18 -0
- package/dist/sandbox-export-command-QCJY4GMV.js +24 -0
- package/dist/static-host-D6KS7X45.js +138 -0
- package/dist/store-BQ97nKIF.d.ts +7760 -0
- package/dist/test-command-TSPBQHBM.js +383 -0
- package/dist/validate-command-4ERHJSCO.js +122 -0
- package/dist/verify-rollout-FAVQ6EJY.js +40 -0
- package/dist/workspace-K72NP7SX.js +49 -0
- package/dist/workspace-command-OF23DPNI.js +156 -0
- package/dist/workspace-export-AJMGN3CQ.js +10 -0
- package/llms/fields.md +104 -0
- package/llms/filters.md +183 -0
- package/llms/kinds-agent-mcp.md +11 -0
- package/llms/kinds-core.md +68 -0
- package/llms/kinds-realtime.md +76 -0
- package/llms/lambda.md +111 -0
- package/llms/legacy.md +43 -0
- package/llms/object-kinds.md +31 -0
- package/llms/statements-calls.md +23 -0
- package/llms/statements-catalog.md +309 -0
- package/llms/statements-data.md +58 -0
- package/llms/statements-runtime.md +48 -0
- package/llms/tests.md +58 -0
- package/llms/triggers.md +22 -0
- package/llms/values.md +29 -0
- package/llms-full.txt +1672 -0
- package/llms.txt +483 -0
- package/manifest.json +9592 -0
- package/package.json +110 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4477 @@
|
|
|
1
|
+
import { e1 as Condition, e2 as FilterResults, e3 as ElementResult, e4 as SameArrayResult, e5 as GroupedArrayResult, e6 as AgentResultOf, aZ as AddonDef, e7 as OutputPath, cO as TableDef, e8 as QualifiedCol, br as DbEval, cN as SortDirective, bt as DbWhere, e9 as OutputRoot, bG as InferRow, ea as AggregateRow, eb as EvalFields, ec as OutputAuthored, c0 as MicroserviceDef, ae as generated, F as FunctionDef, cd as QueryHandle } from './store-BQ97nKIF.js';
|
|
2
|
+
export { a_ as AddonXdo, A as AdoptChange, a as AdoptResult, a$ as AgentDef, b0 as AgentHandle, b1 as AgentOutput, b2 as AgentSettingsXdo, b3 as AgentXdo, b4 as AmbientBindings, b5 as AnthropicLlm, b6 as ApiGroupDef, b7 as ApiGroupXdo, b8 as AuthRef, b9 as Authored, B as Bundle, b as BundlePayload, c as BundleType, ba as Capturable, aW as CaptureRecord, aU as CaptureValue, bb as ChannelConversationDef, bc as ChannelDeliveryDef, bd as ChannelDeliveryGuarantee, be as ChannelPublishDef, bf as ChannelPublishWho, bg as ChannelRateLimitDef, bh as ColumnDef, bi as Comparison, bj as ContainerEnv, bk as ContainerPort, bl as ContainerResources, bm as ContainerVolume, bn as CorsConfig, bo as CorsMode, bp as DatabaseActions, bq as DatabaseInputs, bs as DbEvalFilter, bu as ErrorInputs, bv as ExceptionPolicy, bw as FieldAccessor, bx as FieldRule, by as GoogleGenAiLlm, bz as HistoryInput, bA as HttpVerb, bB as IndexDef, bC as IndexLang, bD as IndexOp, bE as IndexType, bF as IndexXdo, bH as InputDescriptor, bI as InputOptions, bJ as IteratingBindings, bK as LAMBDA_BINDINGS, bL as LAMBDA_CODE_FILTERS, bM as LAMBDA_GLOBALS, bN as LAMBDA_MODULE_GLOBALS, bO as LAMBDA_STATEMENTS, aX as LambdaBindings, bP as LambdaBody, aT as LambdaOptions, aV as LambdaSurface, bQ as LlmPrompt, bR as LlmProvider, bS as LlmSettings, f as LockEntry, g as LockExportContext, h as LockFile, M as Manifest, i as ManifestField, j as ManifestKind, k as ManifestStatement, bT as ManifestValue, bU as McpPathOptions, bV as McpServerDef, bW as McpServerHandle, bX as McpServerXdo, l as MergeResult, bY as MessageDeliverTo, bZ as MicroserviceChart, b_ as MicroserviceConfig, b$ as MicroserviceContainer, c1 as MicroserviceDeployment, c2 as MicroserviceIngress, c3 as MicroserviceRegistryAuth, c4 as MicroserviceVolume, c5 as MicroserviceXdo, c6 as MiddlewareAttach, c7 as MiddlewareAttachEntry, c8 as MiddlewareDef, c9 as MiddlewareXdo, O as ObjectKind, ca as OpenAiLlm, m as PayloadArrayKey, cb as QueryDef, cc as QueryFilterName, ce as QueryResponseType, cf as QueryXdo, cg as RealtimeActions, ch as RealtimeChannelActions, ci as RealtimeChannelDef, cj as RealtimeChannelHandle, ck as RealtimeChannelRef, cl as RealtimeChannelTriggerInputs, cm as RealtimeChannelXdo, cn as RealtimeClient, co as RealtimeInputs, cp as RealtimeMessageDef, cq as RealtimeMessageXdo, cr as RealtimeServerActions, cs as RealtimeServerDef, ct as RealtimeServerHandle, cu as RealtimeServerRef, cv as RealtimeServerTriggerInputs, cw as RealtimeServerXdo, cx as RealtimeUrlOptions, R as RenameResult, cy as ResultStrategy, cz as Route, cA as RowOf, cB as ScheduleDef, cC as SchemaCols, cD as SchemaDef, cE as SearchComparison, cF as SearchGroup, cG as SearchNode, cH as SearchOp, cI as SearchParamValue, cJ as SeedFileSource, cK as SeedRow, cL as SeedSource, cM as SortDir, S as StatementSpec, cP as TableXdo, cQ as TaskDef, cR as TaskXdo, cS as ToolDef, cT as ToolXdo, cU as ToolsetBaseDef, cV as ToolsetBaseXdo, cW as ToolsetInputs, cX as ToolsetToolEntry, cY as ToolsetToolRef, cZ as TriggerDef, c_ as TriggerObjType, c$ as TriggerXdo, d0 as ViewDef, d1 as ViewXdo, d2 as WorkflowTestDef, d3 as WorkflowTestXdo, d4 as WorkspaceActions, d5 as WorkspaceConfigDef, d6 as WorkspaceConfigXdo, d7 as WorkspaceHistoryDef, d8 as WorkspaceHistoryXdo, d9 as WorkspaceInputs, da as WorkspaceMiddlewareDef, db as WorkspaceMiddlewareXdo, aY as Xano, dc as XanoFreeLlm, dd as addon, de as agent, df as agentTrigger, dg as and, dh as apiGroup, di as assertLambdaBody, dj as bitwiseAnd, dk as bitwiseOr, dl as bitwiseXor, dm as cmp, dn as defineFunction, dp as emit, dq as emitBundle, dr as errorTrigger, ds as expr, dt as fl, du as input, ed as lam, dv as mathAdd, dw as mathDiv, dx as mathMul, dy as mathSub, dz as mcpServer, dA as mcpServerTrigger, dB as microservice, dC as middleware, dD as mixed, dE as objectEntries, dF as objectKeys, dG as objectValues, dH as or, dI as query, dJ as realtimeChannel, dK as realtimeChannelTrigger, dL as realtimeMessage, dM as realtimeServer, dN as realtimeServerTrigger, dO as realtimeTrigger, dP as resetLockOverrides, dQ as seedFile, dR as seedLockOverrides, dS as table, dT as tableTrigger, dU as task, dV as textAppend, dW as textPrepend, dX as toSearchParams, dY as tool, dZ as workflowTest, d_ as workspace, d$ as workspaceConfig, e0 as workspaceTrigger } from './store-BQ97nKIF.js';
|
|
3
|
+
import { a2 as StatementAnnotations, a1 as Statement, y as FromFieldMap, w as FilterXdo, V as Value, S as ObjValue, aH as Prettify, x as FilteredValue, X as RefValue, aM as AsShapeBrand, aj as XanoFileRef, a4 as StatementOptions, T as ObjectRef, P as ObjInput, F as FunctionXdo } from './response-CVAE2kMj.js';
|
|
4
|
+
export { B as BrandOpts, c as BrandValue, C as CacheXdo, f as CaughtField, h as ConditionalContext, j as ConditionalElifContext, D as DecimalMethod, E as EmailMethod, k as ExprGroup, l as ExprNode, m as ExprOperand, n as ExprStatement, o as FieldAccess, p as FieldDescriptor, q as FieldMap, s as FieldOpts, u as FieldStyleType, v as FieldXdo, H as HistoryXdo, I as InputXdo, z as IntMethod, L as ListBoundsXdo, M as MethodArg, A as MethodOpts, G as MethodSpec, J as MethodXdo, K as MockEntry, N as MockMap, O as MockXdo, Q as ObjMember, U as PasswordMethod, W as PersistedFunctionRow, Y as RegexValue, Z as ResponseDef, _ as ResultItemXdo, $ as RowFromFieldMap, a0 as StackItemXdo, a3 as StatementInputXdo, a5 as TAGS, a6 as TEST_EXPECT_TYPES, a7 as TableRefMethod, a8 as Tag, a9 as TaggedValue, aa as TestDef, ab as TestExpect, ac as TestExpectType, ad as TestXdo, ae as TextFormat, af as TextMethod, ag as TypeBrand, ah as ValueOf, ai as VectorMethod, ak as XanoGeoPosition, al as XanoGeoValue, am as annotate, an as auth, ao as c, ap as caught, aq as col, ar as env, as as expect, at as f, au as filter, av as inp, aw as obj, ax as out, ay as ref, az as resp, aA as setting, aB as statements, aC as sys, aD as test, aE as toolset, aF as withFilters } from './response-CVAE2kMj.js';
|
|
5
|
+
|
|
6
|
+
/** One `else if (when) { then }` branch of a {@link conditional}'s elif stack. */
|
|
7
|
+
interface ConditionalElifArgs extends StatementAnnotations {
|
|
8
|
+
when: Condition;
|
|
9
|
+
then: Statement[];
|
|
10
|
+
}
|
|
11
|
+
interface ConditionalArgs extends StatementAnnotations {
|
|
12
|
+
when: Condition;
|
|
13
|
+
then: Statement[];
|
|
14
|
+
/** Ordered `else if` branches, each `{ when, then }`. */
|
|
15
|
+
elif?: ConditionalElifArgs[];
|
|
16
|
+
else?: Statement[];
|
|
17
|
+
}
|
|
18
|
+
/** A branching statement: `if (when) { then } [else if …] else { else }`. */
|
|
19
|
+
declare function conditional(args: ConditionalArgs): Statement;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* `InferInput<Q>` (U2) — the request-payload TS type for a query (or function)
|
|
23
|
+
* def's declared inputs, computed at compile time from the value brands added in
|
|
24
|
+
* U1. No codegen, no build step: the type is derived from the def, so it can
|
|
25
|
+
* never drift from what the endpoint actually accepts.
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* const meQuery = query({ verb: "POST", apiGroup: auth, name: "me",
|
|
29
|
+
* input: { email: input.email({ required: true }), password: input.password({ required: true }) } });
|
|
30
|
+
*
|
|
31
|
+
* type MePayload = InferInput<typeof meQuery>; // { email: string; password: string }
|
|
32
|
+
* fetch(BASE + meQuery.getPath(), { body: JSON.stringify(payload satisfies MePayload) });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Works for any def carrying an `input` map, so `defineFunction` handles infer
|
|
36
|
+
* the same way (functions share the input system) even though only queries have
|
|
37
|
+
* a URL path.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The `input` map of a def-like `{ input?: ... }`, or an empty map when absent.
|
|
42
|
+
* The empty case must be `Record<never, never>` (keyof `never`) — NOT
|
|
43
|
+
* `Record<string, never>`, whose string index signature would make
|
|
44
|
+
* {@link FromFieldMap} emit an index-signature payload instead of `{}`.
|
|
45
|
+
*/
|
|
46
|
+
type InputMapOf<Q> = Q extends {
|
|
47
|
+
input?: infer M;
|
|
48
|
+
} ? [M] extends [undefined] ? Record<never, never> : NonNullable<M> : Record<never, never>;
|
|
49
|
+
/**
|
|
50
|
+
* Turn a query/function def's declared `input` map into its request-payload
|
|
51
|
+
* type: required inputs become required keys, the rest optional; `nullable`
|
|
52
|
+
* adds `| null`, `array`/`list` produce `T[]`, `enum` a literal union, and a
|
|
53
|
+
* nested `object` input recurses.
|
|
54
|
+
*/
|
|
55
|
+
type InferInput<Q> = FromFieldMap<InputMapOf<Q>>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Filter-aware result typing — what a value becomes after a filter chain runs.
|
|
59
|
+
*
|
|
60
|
+
* A filter changes the value at runtime, and until now the type system had no
|
|
61
|
+
* way to follow: `withFilters(ref("row"), fl.count())` typed as `unknown`, and a
|
|
62
|
+
* statement's `asFilters` chain did not change the bound variable's type at all
|
|
63
|
+
* (which was worse — the declared type was a confident lie).
|
|
64
|
+
*
|
|
65
|
+
* The engine's own filter catalog declares a `result` for 190 of the 225
|
|
66
|
+
* filters, and {@link FilterResults} turns those declarations into types. This
|
|
67
|
+
* module folds a chain over them, left to right, exactly as the engine applies
|
|
68
|
+
* them — confirmed live: `[fl.first(), fl.get("id")]` over `[{"id":1}]` returns
|
|
69
|
+
* `1`, so each filter genuinely sees the previous one's output.
|
|
70
|
+
*
|
|
71
|
+
* **What this does NOT do.** It does not check that a filter can *accept* the
|
|
72
|
+
* value it is given. A filter applied to an incompatible value returns `null` at
|
|
73
|
+
* runtime rather than erroring — `"ab" |trim|lower|count` is `null`, because
|
|
74
|
+
* `count` is an array filter — so a nonsensical chain still types as its
|
|
75
|
+
* declared result. Modelling filter INPUT types is separate work; this models
|
|
76
|
+
* output only.
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The filter name a {@link FilterXdo} carries at the type level.
|
|
81
|
+
*
|
|
82
|
+
* `fl.upper()` is a `FilterXdo<"upper">`; the bare `filter(someString)` escape
|
|
83
|
+
* hatch and every decoded envelope are `FilterXdo<string>`, which widens to the
|
|
84
|
+
* `string` that {@link ApplyFilter} treats as "not statically known".
|
|
85
|
+
*/
|
|
86
|
+
type NameOf<F> = F extends FilterXdo<infer N> ? N : string;
|
|
87
|
+
/**
|
|
88
|
+
* Apply ONE filter's declared result to `Shape`.
|
|
89
|
+
*
|
|
90
|
+
* Null propagates rather than being erased, matching `IndexShape`'s treatment of
|
|
91
|
+
* a nullable base (#105) and the engine's runtime, where a filter over a null
|
|
92
|
+
* binding yields null: a `db.get` row is `Row | null`, so counting it is
|
|
93
|
+
* `number | null`, not `number`.
|
|
94
|
+
*
|
|
95
|
+
* Anything not in {@link FilterResults} — the `any`-result filters (`get`,
|
|
96
|
+
* `set`, `transform`, `json_decode`, `lambda`, …) and a name that is not
|
|
97
|
+
* statically known — lands on `unknown`. That is the honest floor, and it is
|
|
98
|
+
* where this deliberately stops rather than guessing.
|
|
99
|
+
*/
|
|
100
|
+
type ApplyFilter<Shape, N extends string> = string extends N ? unknown : null extends Shape ? ApplyFilter<Exclude<Shape, null>, N> | null : N extends keyof FilterResults ? FilterResults[N] extends ElementResult ? Shape extends readonly (infer E)[] ? E : unknown : FilterResults[N] extends SameArrayResult ? Shape extends readonly unknown[] ? Shape : unknown : FilterResults[N] extends GroupedArrayResult ? Shape extends readonly (infer E)[] ? Record<string, E[]> : unknown : FilterResults[N] : unknown;
|
|
101
|
+
/**
|
|
102
|
+
* Fold a whole chain over `Shape`, left to right.
|
|
103
|
+
*
|
|
104
|
+
* An empty chain leaves the shape untouched, so attaching no filters is exactly
|
|
105
|
+
* the same type as attaching none — `asFilters: []` does not degrade anything.
|
|
106
|
+
*/
|
|
107
|
+
type ApplyFilters<Shape, Fs> = Fs extends readonly [infer Head, ...infer Tail] ? ApplyFilters<ApplyFilter<Shape, NameOf<Head>>, Tail> : Fs extends readonly [] ? Shape : unknown;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* `InferResponse<Q>` (issue #5) — the response type for a query or function def,
|
|
111
|
+
* the read-side counterpart of `InferInput`. Closes the round trip: rename or
|
|
112
|
+
* retype what an endpoint returns and every consumer that types a response
|
|
113
|
+
* against `InferResponse` lights up at compile time.
|
|
114
|
+
*
|
|
115
|
+
* ```ts
|
|
116
|
+
* const listLinks = query({ verb: "GET", apiGroup: links, name: "list_links",
|
|
117
|
+
* stack: [s.db.query({ table: link, as: "rows" })], response: ref("rows"),
|
|
118
|
+
* responseShape: [] as InferRow<typeof link>[] });
|
|
119
|
+
*
|
|
120
|
+
* type Links = InferResponse<typeof listLinks>; // InferRow<typeof link>[]
|
|
121
|
+
* const res = await fetch(BASE + listLinks.getPath());
|
|
122
|
+
* const links: Links = await res.json(); // typed end to end
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* **Hybrid resolution** (mirrors how the Xano engine derives its OpenAPI response
|
|
126
|
+
* schema — a static walk that degrades to `json` where truth isn't statically
|
|
127
|
+
* knowable):
|
|
128
|
+
* 1. A declared `responseShape` on the def always wins (the override).
|
|
129
|
+
* 2. Otherwise the shape is auto-derived from `response` + `stack`
|
|
130
|
+
* ({@link DeriveResponse}) — object-literal keys (U2) and a single variable
|
|
131
|
+
* traced to a typed `db.get`/`db.query` (U5). A dotted `ref("var.field")`
|
|
132
|
+
* traces the base variable, then indexes the subpath into its shape (#93).
|
|
133
|
+
* 3. Anything the walk can't resolve (filters, lambdas, control-flow vars,
|
|
134
|
+
* `set_var`, function-produced vars, streams) resolves to `unknown`, which
|
|
135
|
+
* the author narrows or overrides via `responseShape`.
|
|
136
|
+
*/
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The author-declared response shape, read from a def's `responseShape` field
|
|
140
|
+
* (captured by `query()`/`defineFunction()`), or `never` when undeclared.
|
|
141
|
+
*
|
|
142
|
+
* Read structurally rather than off the `Res` type argument: an undeclared def
|
|
143
|
+
* carries `responseShape?: never`, whose optional-collapsed field type is
|
|
144
|
+
* `undefined` — the `[R] extends [undefined]` gate maps that to `never` (→ route
|
|
145
|
+
* to derivation). A declared shape's field type is `T | undefined`; stripping the
|
|
146
|
+
* optional `undefined` with `Exclude` recovers `T` **while preserving a
|
|
147
|
+
* deliberate `| null`** (e.g. `InferRow<...> | null` stays nullable).
|
|
148
|
+
*/
|
|
149
|
+
type DeclaredResponse<Q> = Q extends {
|
|
150
|
+
responseShape?: infer R;
|
|
151
|
+
} ? [R] extends [undefined] ? never : Exclude<R, undefined> : never;
|
|
152
|
+
/**
|
|
153
|
+
* Search a branded stack tuple `S` for the read statement that bound the
|
|
154
|
+
* variable `Name` (its phantom `__as`), returning that statement's `__shape`.
|
|
155
|
+
* Mirrors the engine's `findVarSchema`: a one-hop, top-level match. Statements
|
|
156
|
+
* without the `__as`/`__shape` brand (`set_var`, control flow, function calls)
|
|
157
|
+
* are skipped, so a ref into one of those falls through to `unknown` — exactly
|
|
158
|
+
* where the engine falls back to `json`. A widened (non-tuple) stack matches no
|
|
159
|
+
* head and yields `unknown` too.
|
|
160
|
+
*/
|
|
161
|
+
/**
|
|
162
|
+
* What a response resolves to when the stack is a plain `Statement[]` rather
|
|
163
|
+
* than a tuple — the collapse issue #11 reported.
|
|
164
|
+
*
|
|
165
|
+
* A widened stack has no heads to walk, so EVERY `as` binding in it is invisible
|
|
166
|
+
* and every `ref()` bottoms out. Resolving that to `unknown` made the failure
|
|
167
|
+
* silent and moved the error downstream ("Property 'model_id' does not exist on
|
|
168
|
+
* type '{}'", in the page that consumes the response). Resolving it to this
|
|
169
|
+
* named type puts the cause and the two fixes in the error itself.
|
|
170
|
+
*
|
|
171
|
+
* The cause is almost always a shared helper typed `Statement[]` spread into the
|
|
172
|
+
* stack: `...assertOk("res")`. Return `statements(...)` from the helper to keep
|
|
173
|
+
* the tuple, or declare `responseShape` on this def.
|
|
174
|
+
*/
|
|
175
|
+
interface StackTupleWidened {
|
|
176
|
+
readonly __xanots_response_not_inferred: "This stack is a `Statement[]`, not a tuple, so no `as` binding in it can be traced. A helper returning `Statement[]` and spread into the stack is the usual cause: return `statements(...)` from the helper (fixed arity), or declare `responseShape` on this def.";
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Is `S` a widened array (not a fixed tuple)? A fixed tuple's `length` is a
|
|
180
|
+
* literal. A REST tuple (`[DbGet, ...Statement[]]` — what a stack with a helper
|
|
181
|
+
* spread at the END looks like) has a `number` length too, which is why the
|
|
182
|
+
* report below is gated on the trace actually failing rather than on this
|
|
183
|
+
* alone: a binding declared before the spread still traces perfectly.
|
|
184
|
+
*/
|
|
185
|
+
type IsWidenedStack<S> = S extends readonly unknown[] ? number extends S["length"] ? true : false : false;
|
|
186
|
+
/**
|
|
187
|
+
* Report the collapse only where it actually happened: an unresolved value
|
|
188
|
+
* (`unknown`) against a stack whose tuple was widened. A ref that still traced —
|
|
189
|
+
* because it was bound before the spread, in a rest tuple — keeps its type, and
|
|
190
|
+
* an unresolvable ref in a proper tuple keeps the honest `unknown` floor (it is
|
|
191
|
+
* a filter/lambda/control-flow case, not a widening one).
|
|
192
|
+
*/
|
|
193
|
+
type ReportWidened<T, S> = IsWidenedStack<S> extends true ? unknown extends T ? StackTupleWidened : T : T;
|
|
194
|
+
type TraceBinding<Name extends string, S> = S extends readonly [infer Head, ...infer Tail] ? Head extends AsShapeBrand<infer As, infer Shape> ? As extends Name ? Name extends As ? Shape : TraceBinding<Name, Tail> : TraceBinding<Name, Tail> : TraceBinding<Name, Tail> : unknown;
|
|
195
|
+
/**
|
|
196
|
+
* Walk a dotted subpath `Path` into an already-traced binding `Shape`, one
|
|
197
|
+
* segment at a time: `IndexShape<AgentRunResult<string>, "result">` → `string`.
|
|
198
|
+
*
|
|
199
|
+
* **Null-propagating** (#105): when the base is nullable (e.g. a `db.get` row,
|
|
200
|
+
* `Row | null`), the null flows *through* the projection rather than erasing it —
|
|
201
|
+
* `IndexShape<Row | null, "slug">` → `string | null`, mirroring the engine's
|
|
202
|
+
* runtime where `$row.slug` on a missed (null) row is itself null. Without this,
|
|
203
|
+
* `keyof (Row | null)` narrows to `never` and every dotted ref into a nullable
|
|
204
|
+
* base would bottom out at `unknown`, silently dropping the #93 projection.
|
|
205
|
+
*
|
|
206
|
+
* A segment that genuinely isn't a key of the (non-null) shape — including a
|
|
207
|
+
* shape that is already `unknown` (whose `keyof` is `never`) — still bottoms out
|
|
208
|
+
* at `unknown`, the same honest floor as an untraceable whole ref.
|
|
209
|
+
*/
|
|
210
|
+
type IndexShape<Shape, Path extends string> = unknown extends Shape ? IndexStep<Shape, Path> : null extends Shape ? IndexShape<Exclude<Shape, null>, Path> | null : undefined extends Shape ? IndexShape<Exclude<Shape, undefined>, Path> | undefined : IndexStep<Shape, Path>;
|
|
211
|
+
/**
|
|
212
|
+
* One non-null indexing step for {@link IndexShape}: split the head segment off
|
|
213
|
+
* `Path` and project it into `Shape`, recursing (back through the null-aware
|
|
214
|
+
* {@link IndexShape}) for the tail. A segment that isn't a key bottoms out at
|
|
215
|
+
* `unknown`. Kept separate so the `unknown extends Shape` guard in `IndexShape`
|
|
216
|
+
* (true for exactly `unknown`/`any` — the bases where null-distribution can't
|
|
217
|
+
* terminate) routes straight here without looping.
|
|
218
|
+
*/
|
|
219
|
+
type IndexStep<Shape, Path extends string> = Path extends `${infer Head}.${infer Rest}` ? Head extends keyof Shape ? IndexShape<Shape[Head], Rest> : unknown : Path extends keyof Shape ? Shape[Path] : unknown;
|
|
220
|
+
/**
|
|
221
|
+
* Resolve a `ref` name against the branded stack `S`. A **dotted** name projects
|
|
222
|
+
* a subpath (#93): the head names the bound variable (traced via
|
|
223
|
+
* {@link TraceBinding}) and the tail indexes into that variable's shape (via
|
|
224
|
+
* {@link IndexShape}), so `ref("generated.result")` types to the completion, not
|
|
225
|
+
* `unknown`. A bare name traces the whole binding. Stack-variable names are
|
|
226
|
+
* identifiers (no dots), so the first `.` always splits the variable from the
|
|
227
|
+
* subpath — matching how the engine resolves `$generated.result`.
|
|
228
|
+
*/
|
|
229
|
+
type TraceVar<Name extends string, S> = Name extends `${infer Base}.${infer Path}` ? IndexShape<TraceBinding<Base, S>, Path> : TraceBinding<Name, S>;
|
|
230
|
+
/**
|
|
231
|
+
* Resolve one response {@link Value} to its type against the branded stack `S`.
|
|
232
|
+
*
|
|
233
|
+
* A FILTERED value resolves its base and then folds the chain over it
|
|
234
|
+
* ({@link ApplyFilters}), so `withFilters(ref("rows"), fl.count())` is `number`
|
|
235
|
+
* rather than `unknown`. It used to degrade to `unknown` outright, on the
|
|
236
|
+
* grounds that a filter reshapes a value with no static signal — true when
|
|
237
|
+
* written, but the catalog does declare a result for 190 of the 225 filters, and
|
|
238
|
+
* those declarations are live-verified. The remaining filters (`get`, `set`,
|
|
239
|
+
* `json_decode`, …) still land on `unknown` through the fold itself.
|
|
240
|
+
*
|
|
241
|
+
* Otherwise a branded `ref` traces to the statement that produced it
|
|
242
|
+
* ({@link TraceVar}); anything else (a non-ref value, an untraceable ref) is
|
|
243
|
+
* `unknown` — the honest floor.
|
|
244
|
+
*
|
|
245
|
+
* A CONSTANT is "anything else". `response: { success: c.bool(true) }` derives
|
|
246
|
+
* `{ success: unknown }`, not `{ success: boolean }` — `c.*` returns a bare
|
|
247
|
+
* `Value` carrying no tag brand, so there is nothing here to read the type off.
|
|
248
|
+
* That mirrors the engine's own static walk, which resolves references and not
|
|
249
|
+
* values, and it is deliberate rather than a gap: typing a constant's key would
|
|
250
|
+
* mean branding the return of every constant constructor, and `Value` is the
|
|
251
|
+
* currency of every statement field in the SDK. Declare `responseShape` when a
|
|
252
|
+
* client needs those keys typed (issue #79).
|
|
253
|
+
*/
|
|
254
|
+
type ResolveValue<V, S> = V extends ObjValue<infer Members> ? ResolveObj<Members, S> : V extends FilteredValue<infer Base, infer Chain> ? ApplyFilters<ResolveValue<Base, S>, Chain> : V extends RefValue<infer Name> ? TraceVar<Name, S> : unknown;
|
|
255
|
+
/**
|
|
256
|
+
* Resolve every member of an {@link ObjValue}'s record (issue #118) — the same
|
|
257
|
+
* walk {@link DeriveResponse} runs over a top-level object literal, one level
|
|
258
|
+
* down. `obj()` is the SDK's answer for a nested response object, and it used to
|
|
259
|
+
* cost the caller its types: the members are ordinary {@link Value}s with
|
|
260
|
+
* ordinary bindings, so there was never a reason they could not trace.
|
|
261
|
+
*
|
|
262
|
+
* The widened-stack report ({@link ReportWidened}) is applied per MEMBER rather
|
|
263
|
+
* than to the record as a whole, so a collapsed tuple still names itself at the
|
|
264
|
+
* leaf that failed — `{ user: { id: StackTupleWidened } }` — instead of
|
|
265
|
+
* flattening back into a silent `unknown`.
|
|
266
|
+
*
|
|
267
|
+
* A dynamically-built `ObjInput` (no literal to read) maps its index signature
|
|
268
|
+
* and lands on `{ [key: string]: unknown }` — the honest floor, same as any other
|
|
269
|
+
* value the walk cannot see through.
|
|
270
|
+
*/
|
|
271
|
+
type ResolveObj<Members, S> = Prettify<{
|
|
272
|
+
-readonly [K in keyof Members]: ReportWidened<ResolveMember<Members[K], S>, S>;
|
|
273
|
+
}>;
|
|
274
|
+
/**
|
|
275
|
+
* Resolve one {@link ObjMember} — the member grammar `obj()` accepts, which is
|
|
276
|
+
* wider than {@link Value}.
|
|
277
|
+
*
|
|
278
|
+
* The branch order is load-bearing:
|
|
279
|
+
* - a {@link Value} (including a nested `obj()`, a filtered value, or a `ref`)
|
|
280
|
+
* goes to {@link ResolveValue}, so `c.*` constants keep the `unknown` floor
|
|
281
|
+
* issue #79 documents;
|
|
282
|
+
* - a RAW SCALAR literal types itself — `obj({ count: 3 })` really is a number,
|
|
283
|
+
* and unlike `c.int(3)` the type is right there to read. A boolean is widened
|
|
284
|
+
* explicitly because inference does not treat it like its siblings: `3` and
|
|
285
|
+
* `"hi"` widen to `number`/`string` against the `ObjMember` contextual type,
|
|
286
|
+
* while `true` survives as the literal (it is a member of `boolean` itself).
|
|
287
|
+
* Uniform scalars beat one field inferring narrower than the rest for no
|
|
288
|
+
* reason the author can see; `responseShape` states a literal deliberately;
|
|
289
|
+
* - an ARRAY resolves element-wise (checked before the record branch, since an
|
|
290
|
+
* array is also an object);
|
|
291
|
+
* - a nested plain RECORD recurses. This is the spelling `response: { user: {
|
|
292
|
+
* id: ref(...) } }` uses — the #133 auto-wrap, which `encodeResponse` hands
|
|
293
|
+
* to `obj()` anyway, so the two spellings must and now do infer alike.
|
|
294
|
+
*/
|
|
295
|
+
type ResolveMember<M, S> = M extends Value ? ResolveValue<M, S> : M extends boolean ? boolean : M extends string | number ? M : M extends readonly (infer Element)[] ? ResolveMember<Element, S>[] : M extends object ? ResolveObj<M, S> : unknown;
|
|
296
|
+
/**
|
|
297
|
+
* Best-effort automatic derivation of a response shape from the def's `response`
|
|
298
|
+
* field and branded `stack`. Mirrors the Xano engine's static walk:
|
|
299
|
+
* - a record response (object literal) → an object with **those keys** (each
|
|
300
|
+
* member resolved individually, recursing into a nested `obj()` or plain
|
|
301
|
+
* object literal — #118); keys are known regardless of traceability;
|
|
302
|
+
* - a single {@link Value} response → resolve it against the stack;
|
|
303
|
+
* - no response / an unresolvable shape → `unknown`.
|
|
304
|
+
* Kept separate from {@link DeclaredResponse} so the user override always wins.
|
|
305
|
+
*/
|
|
306
|
+
type DeriveResponse<Q> = Q extends {
|
|
307
|
+
response?: infer Resp;
|
|
308
|
+
stack?: infer S;
|
|
309
|
+
} ? [Resp] extends [undefined] ? unknown : Resp extends Value ? ReportWidened<ResolveValue<Resp, S>, S> : Resp extends Record<string, unknown> ? Prettify<{
|
|
310
|
+
-readonly [K in keyof Resp]: ReportWidened<ResolveMember<Resp[K], S>, S>;
|
|
311
|
+
}> : unknown : unknown;
|
|
312
|
+
/**
|
|
313
|
+
* Recover a query/function's response type. A declared `responseShape` wins;
|
|
314
|
+
* otherwise fall back to automatic derivation (which itself bottoms out at
|
|
315
|
+
* `unknown` for anything the static walk can't resolve).
|
|
316
|
+
*/
|
|
317
|
+
type InferResponse<Q> = [DeclaredResponse<Q>] extends [never] ? DeriveResponse<Q> : DeclaredResponse<Q>;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Addressing a stored file from a client (issue #31).
|
|
321
|
+
*
|
|
322
|
+
* A file column comes back as a {@link XanoFileRef}: a `path` into the vault
|
|
323
|
+
* plus metadata, and an absolute, authoritative-looking `url`. On a
|
|
324
|
+
* tenant-scoped environment — which is what `xanots deploy` provisions — that
|
|
325
|
+
* `url` addresses the instance host and OMITS the `/tenant/<name>` segment every
|
|
326
|
+
* other URL on that environment carries, so it 404s. The `path` is correct; only
|
|
327
|
+
* the host prefix is wrong.
|
|
328
|
+
*
|
|
329
|
+
* It fails as a broken `<img>` and nothing else: the API response is complete
|
|
330
|
+
* and every assertion about it passes, because the field IS present, with a real
|
|
331
|
+
* `size` and real `meta.width`/`meta.height`. Only fetching the URL reveals it.
|
|
332
|
+
*
|
|
333
|
+
* {@link fileUrl} joins `path` to the base URL the client already has, which is
|
|
334
|
+
* correct on a tenant-scoped environment and on an instance workspace alike.
|
|
335
|
+
* Use it instead of reading `url` directly.
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* The URL to fetch a stored file from, built against the base URL the client is
|
|
340
|
+
* already talking to.
|
|
341
|
+
*
|
|
342
|
+
* ```ts
|
|
343
|
+
* <img src={fileUrl(row.avatar, XANO_HOST) ?? ""} />
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* `XANO_HOST` is the backend base URL `xanots deploy --static` injects (and
|
|
347
|
+
* `xanots sandbox details` prints) — on an ephemeral it already carries the
|
|
348
|
+
* `/tenant/<name>` segment, which is exactly the part the file's own `url` field
|
|
349
|
+
* drops.
|
|
350
|
+
*
|
|
351
|
+
* Returns `null` for an absent file, so it composes with an optional column.
|
|
352
|
+
* Falls back to the file's own `url` only when there is no `path` to join.
|
|
353
|
+
*/
|
|
354
|
+
declare function fileUrl(file: XanoFileRef | null | undefined, baseUrl: string): string | null;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* `setVar` / `updateVar` statements (U5/U10) — the `!var` family. Both carry
|
|
358
|
+
* their value in `context` (not `input[]`), a per-statement quirk confirmed by
|
|
359
|
+
* the golden fixtures. They differ in how the target variable is named:
|
|
360
|
+
*
|
|
361
|
+
* - `set_var` declares a *new* stack variable via the top-level `as` slot
|
|
362
|
+
* (`var $x1 { value = ... }`) and emits no `output` envelope.
|
|
363
|
+
* - `update_var` reassigns an *existing* stack variable named inside
|
|
364
|
+
* `context.name` (`update $x1 { value = ... }`), has no `as`, and carries a
|
|
365
|
+
* lean `output:{filters:[]}` envelope.
|
|
366
|
+
*/
|
|
367
|
+
|
|
368
|
+
/** Assign `value` to stack variable `as` (`var $as { value = ... }`). */
|
|
369
|
+
declare function setVar(as: string, value: Value, a?: StatementOptions): Statement;
|
|
370
|
+
/** Reassign existing stack variable `name` to `value` (`update $name { value = ... }`). */
|
|
371
|
+
declare function updateVar(name: string, value: Value, a?: StatementAnnotations): Statement;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Hand-authored `!class` control-flow / terminal statements (U10). These carry
|
|
375
|
+
* PHP transforms in the engine, so they're authored by hand and validated
|
|
376
|
+
* against persisted fixtures rather than codegen'd. (`conditional` — also a
|
|
377
|
+
* `!class` special — already lives in `src/statements/conditional.ts`.)
|
|
378
|
+
*
|
|
379
|
+
* - `return` / `die` / `debug_log`: carry a single Value in `context`.
|
|
380
|
+
* - `foreach_break` / `foreach_continue` / `foreach_remove`: empty `context`.
|
|
381
|
+
*/
|
|
382
|
+
|
|
383
|
+
/** Accept either a bare `Value` or the object form `{ value }` for ergonomics. */
|
|
384
|
+
type ValueArg = Value | {
|
|
385
|
+
value: Value;
|
|
386
|
+
};
|
|
387
|
+
/** `return <value>` — terminate and return a value. */
|
|
388
|
+
declare function returnValue(value: ValueArg, a?: StatementAnnotations): Statement;
|
|
389
|
+
/**
|
|
390
|
+
* `die <value>` — terminate the request with an error value.
|
|
391
|
+
*
|
|
392
|
+
* The same statement as `s.debug.stop` (both emit `mvp:die`), and the one flat
|
|
393
|
+
* alias whose name does not mirror its `s.*` path — there is no `s.die`. Despite
|
|
394
|
+
* living under `debug`, it is real control flow rather than a development aid.
|
|
395
|
+
* Compare `s.throw`, which raises a catchable named error.
|
|
396
|
+
*/
|
|
397
|
+
declare function die(value: ValueArg, a?: StatementAnnotations): Statement;
|
|
398
|
+
/** `debug_log <value>` — emit a debug log entry. */
|
|
399
|
+
declare function debugLog(value: ValueArg, a?: StatementAnnotations): Statement;
|
|
400
|
+
/** `foreach_break` — break out of the enclosing loop. */
|
|
401
|
+
declare function foreachBreak(a?: StatementAnnotations): Statement;
|
|
402
|
+
/** `foreach_continue` — continue the enclosing loop. */
|
|
403
|
+
declare function foreachContinue(a?: StatementAnnotations): Statement;
|
|
404
|
+
/** `foreach_remove` — remove the current item from the iterated collection. */
|
|
405
|
+
declare function foreachRemove(a?: StatementAnnotations): Statement;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Hand-authored control-flow block statements (U10). These carry non-trivial
|
|
409
|
+
* transforms in the engine (for, foreach, while, group), so they're authored by
|
|
410
|
+
* hand — like `conditional` — rather than codegen'd. Each nests a `run[]` stack
|
|
411
|
+
* encoded through the shared statement encoder, and `while` reuses the
|
|
412
|
+
* conditional's `encodeComparison`.
|
|
413
|
+
*
|
|
414
|
+
* Stored shapes (from the Xano engine's persisted for/foreach/while shapes):
|
|
415
|
+
* for → context: { as, cnt:<Value>, run:[…] }
|
|
416
|
+
* foreach → context: { as, list:<Value>, run:[…] }
|
|
417
|
+
* while → context: { expr:<comparison>, run:[…] }
|
|
418
|
+
* group → context: { run:[…] }
|
|
419
|
+
*
|
|
420
|
+
* All four are golden-verified: `for`/`foreach` from vendored goldens, and
|
|
421
|
+
* `while`/`group` from live engine captures (see the conformance corpus). The
|
|
422
|
+
* `while` shape (`expr` comparison + `run[]`) and `group`'s bare `{run}` are
|
|
423
|
+
* confirmed byte-exact.
|
|
424
|
+
*/
|
|
425
|
+
|
|
426
|
+
interface ForArgs extends StatementOptions {
|
|
427
|
+
/** Loop variable name (the index). */
|
|
428
|
+
as: string;
|
|
429
|
+
/** Iteration count. */
|
|
430
|
+
count: Value;
|
|
431
|
+
body: Statement[];
|
|
432
|
+
}
|
|
433
|
+
/** `for (as in 0..count) { body }` — count-bounded loop. */
|
|
434
|
+
declare function forLoop(args: ForArgs): Statement;
|
|
435
|
+
interface ForeachArgs extends StatementOptions {
|
|
436
|
+
/** Loop variable name (the current item). */
|
|
437
|
+
as: string;
|
|
438
|
+
/** The list to iterate. */
|
|
439
|
+
list: Value;
|
|
440
|
+
body: Statement[];
|
|
441
|
+
}
|
|
442
|
+
/** `foreach (as of list) { body }` — list iteration. */
|
|
443
|
+
declare function foreachLoop(args: ForeachArgs): Statement;
|
|
444
|
+
interface WhileArgs extends StatementAnnotations {
|
|
445
|
+
when: Condition;
|
|
446
|
+
body: Statement[];
|
|
447
|
+
}
|
|
448
|
+
/** `while (when) { body }` — condition-bounded loop. */
|
|
449
|
+
declare function whileLoop(args: WhileArgs): Statement;
|
|
450
|
+
/** `group { body }` — a labeled block grouping a sub-stack. */
|
|
451
|
+
declare function group(body: Statement[], a?: StatementAnnotations): Statement;
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Hand-authored branching block statements (U10) — `switch` and `try_catch`.
|
|
455
|
+
* Both carry structural control-flow transforms in the engine, so
|
|
456
|
+
* (like `conditional` and the loops) they're authored by hand rather than
|
|
457
|
+
* codegen'd. Each nests `run[]` stacks encoded through the shared statement
|
|
458
|
+
* encoder.
|
|
459
|
+
*
|
|
460
|
+
* Stored shapes (from the Xano engine's persisted switch / try_catch shapes):
|
|
461
|
+
* switch → context: { value:<Value>, elif:{ run:[switch_case…] }, else:{ run:[…] } }
|
|
462
|
+
* switch_case → context: { value:<Value>, break?:bool, if:{ run:[…] } }
|
|
463
|
+
* try_catch → context: { if:{ run:[…try…] }, else:{ run:[…catch…] }, then:{ run:[…finally…] } }
|
|
464
|
+
*
|
|
465
|
+
* In `switch`, `value` is the subject being matched and each `switch_case`'s
|
|
466
|
+
* `value` is the literal a case compares against; `else.run` is the `default`
|
|
467
|
+
* block. `break` (fallthrough control) is omitted unless explicitly set, matching
|
|
468
|
+
* the golden fixture. In `try_catch`, the engine maps try→`if`, catch→`else`,
|
|
469
|
+
* finally→`then`; all three blocks are always emitted (engine `exportContext`
|
|
470
|
+
* normalizes each to `{ run: [] }`).
|
|
471
|
+
*/
|
|
472
|
+
|
|
473
|
+
interface SwitchCaseArgs extends StatementAnnotations {
|
|
474
|
+
/** The literal this case matches against the switch subject. */
|
|
475
|
+
when: Value;
|
|
476
|
+
/** Statements run when this case matches. */
|
|
477
|
+
body: Statement[];
|
|
478
|
+
/**
|
|
479
|
+
* Whether to stop after this case (`true`) or fall through to the next
|
|
480
|
+
* (`false`). Omitted from the stored shape entirely when not set.
|
|
481
|
+
*/
|
|
482
|
+
break?: boolean;
|
|
483
|
+
}
|
|
484
|
+
/** A single `case (when) { body }` clause of a `switch`. */
|
|
485
|
+
declare function switchCase(args: SwitchCaseArgs): Statement;
|
|
486
|
+
interface SwitchArgs extends StatementAnnotations {
|
|
487
|
+
/** The subject value being matched. */
|
|
488
|
+
on: Value;
|
|
489
|
+
/** Ordered `case` clauses. */
|
|
490
|
+
cases: SwitchCaseArgs[];
|
|
491
|
+
/** The `default` block, run when no case matches. */
|
|
492
|
+
default?: Statement[];
|
|
493
|
+
}
|
|
494
|
+
/** `switch (on) { case … default … }` — multi-way branch. */
|
|
495
|
+
declare function switchStatement(args: SwitchArgs): Statement;
|
|
496
|
+
interface TryCatchArgs extends StatementAnnotations {
|
|
497
|
+
/** The protected block (engine `if`). */
|
|
498
|
+
try: Statement[];
|
|
499
|
+
/** Error-handler block (engine `else`). */
|
|
500
|
+
catch?: Statement[];
|
|
501
|
+
/** Always-run block (engine `then`). */
|
|
502
|
+
finally?: Statement[];
|
|
503
|
+
}
|
|
504
|
+
/** `try_catch { try … catch … finally … }` — error handling block. */
|
|
505
|
+
declare function tryCatch(args: TryCatchArgs): Statement;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Shared coercion plumbing for the hand-authored statement wrappers — the units
|
|
509
|
+
* that turn an ergonomic, literal-friendly authored field into the `Value` the
|
|
510
|
+
* generated factory encodes, so the wrapper delegates for byte-parity.
|
|
511
|
+
*
|
|
512
|
+
* Two families live here. The HTTP-request fields (`api.request`,
|
|
513
|
+
* `stream.from_request`, `webflow.request`, `microservice.request`) were hoisted
|
|
514
|
+
* per the rule of three once the second wrapper landed. The DB row CELL joined
|
|
515
|
+
* them (issue #92): it is a self-contained coercion unit that landed in `db.ts`
|
|
516
|
+
* only because that is where its caller is, and its siblings — `coerceScalar`,
|
|
517
|
+
* `coerceObj`, `coerceHeaders` — were already here.
|
|
518
|
+
*/
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* The HTTP verbs the engine's runtime input schema accepts. Enforced: the
|
|
522
|
+
* wrapper coerces to a `Value` and delegates to the generated factory, whose
|
|
523
|
+
* spec now carries the same set and rejects a constant outside it.
|
|
524
|
+
*/
|
|
525
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH";
|
|
526
|
+
/** A headers map: full header lines built from `Name: value` pairs (issue #72). */
|
|
527
|
+
type HeaderMap = Readonly<Record<string, string | Value>>;
|
|
528
|
+
/**
|
|
529
|
+
* A value acceptable in a call/agent `input` map — a raw scalar literal, a nested
|
|
530
|
+
* object/array, or a tagged {@link Value}. Widening the maps to this lets
|
|
531
|
+
* `input: { max_age_days: 3 }` compile without wrapping every literal in `c.int`.
|
|
532
|
+
*/
|
|
533
|
+
type InputValue = string | number | boolean | object | Value;
|
|
534
|
+
/** The shared TLS/HTTP fields carried by `api.request` / `stream.from_request` / `webflow.request`. */
|
|
535
|
+
interface HttpRequestFields {
|
|
536
|
+
method?: HttpMethod | (string & {}) | Value;
|
|
537
|
+
params?: object | Value;
|
|
538
|
+
headers?: readonly string[] | HeaderMap | Value;
|
|
539
|
+
timeout?: number | Value;
|
|
540
|
+
follow_location?: boolean | Value;
|
|
541
|
+
verify_host?: boolean | Value;
|
|
542
|
+
verify_peer?: boolean | Value;
|
|
543
|
+
ca_certificate?: string | Value;
|
|
544
|
+
certificate?: string | Value;
|
|
545
|
+
certificate_pass?: string | Value;
|
|
546
|
+
private_key?: string | Value;
|
|
547
|
+
private_key_pass?: string | Value;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* The bare JS literals a row cell accepts for a column whose row type is `V`,
|
|
551
|
+
* mirroring the `Scalar` union `fl.*` arguments and `seed` rows already take
|
|
552
|
+
* (issue #75).
|
|
553
|
+
*
|
|
554
|
+
* Keyed on the column's own inferred type, so the widening is STRICTER than the
|
|
555
|
+
* tagged spelling it replaces: `{ is_hidden: "yes" }` on an `f.bool()` column is
|
|
556
|
+
* a compile error here, where `{ is_hidden: c.text("yes") }` was always accepted.
|
|
557
|
+
* An `f.enum` column keeps its literal union, so a non-member is refused too.
|
|
558
|
+
*
|
|
559
|
+
* `null` is admitted on EVERY column, including the ones that refuse every other
|
|
560
|
+
* literal — an `obj`/`json`/list/`geo`/`vector` column has no bare-literal form
|
|
561
|
+
* and throws for a string, number or boolean, but takes `null`. That asymmetry
|
|
562
|
+
* is the decision, not an oversight (issue #90): nulling a cell is a legitimate
|
|
563
|
+
* write whatever the column reads back as, and it matches what a seed row does
|
|
564
|
+
* with a `null` (see `coerceScalarValue` — nullability is the engine's to
|
|
565
|
+
* enforce, and a column config this layer does not fully model is not something
|
|
566
|
+
* to guess at). Two consequences worth knowing, both stated on the grounding
|
|
567
|
+
* surface: on a column with no literal form, `null` is the ONLY literal the cell
|
|
568
|
+
* type offers; and an explicit `null` is not the same as omitting the key, which
|
|
569
|
+
* takes the type default in {@link defaultCell} instead.
|
|
570
|
+
*
|
|
571
|
+
* A column whose inferred value is `unknown` — a raw `ColumnDef[]` schema, or an
|
|
572
|
+
* `f.json()` column, which reads back as `unknown` by construction — has nothing
|
|
573
|
+
* to key on, so it falls back to the whole scalar union and leans on the
|
|
574
|
+
* encoder's own check. The escape hatch is not made stricter than it was.
|
|
575
|
+
*/
|
|
576
|
+
type ScalarCell<V> = [unknown] extends [V] ? string | number | boolean | null : (V extends string | number | boolean ? V : never) | null;
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Background execution for a call statement.
|
|
580
|
+
*
|
|
581
|
+
* Shared by `function.run` and `ai.agent.run`: the engine reads the SAME
|
|
582
|
+
* top-level `runtime` block for both, in one `switch` over `runtime.mode`.
|
|
583
|
+
* Keeping the model in one place is what stops the two surfaces drifting into
|
|
584
|
+
* different vocabularies — which is exactly what had happened before this
|
|
585
|
+
* module existed.
|
|
586
|
+
*/
|
|
587
|
+
/**
|
|
588
|
+
* How a call executes: synchronously (the default), or in the background on
|
|
589
|
+
* shared or dedicated async workers.
|
|
590
|
+
*
|
|
591
|
+
* Stored as a TOP-LEVEL `runtime` block on the stack item — not inside
|
|
592
|
+
* `context`. The engine switches on `runtime.mode` and treats every value
|
|
593
|
+
* outside this union (including the absent block and the editor's explicit
|
|
594
|
+
* `"disabled"`) as synchronous.
|
|
595
|
+
*
|
|
596
|
+
* Async is not a performance knob — it changes what the statement returns.
|
|
597
|
+
* `mvp:function` is rewritten to `mvp:async_function`, so the call no longer
|
|
598
|
+
* yields the function's result; it dispatches and continues. Pair it with
|
|
599
|
+
* `s.await(...)` to collect results.
|
|
600
|
+
*/
|
|
601
|
+
type AsyncMode = "async-shared" | "async-dedicated";
|
|
602
|
+
/** Background execution settings for a call. */
|
|
603
|
+
interface AsyncRuntime {
|
|
604
|
+
/**
|
|
605
|
+
* `"async-shared"` runs on the instance's pooled async workers and reads no
|
|
606
|
+
* other member here. `"async-dedicated"` reserves its own resources and is
|
|
607
|
+
* the only mode for which `cpu`/`memory`/`timeout`/`maxRetry` are read.
|
|
608
|
+
*/
|
|
609
|
+
mode: AsyncMode;
|
|
610
|
+
/** Dedicated only. Kubernetes CPU request — e.g. `"100m"`, `"250m"`, `"500m"`. */
|
|
611
|
+
cpu?: string;
|
|
612
|
+
/** Dedicated only. Kubernetes memory request — e.g. `"256Mi"`, `"512Mi"`, `"1Gi"`. */
|
|
613
|
+
memory?: string;
|
|
614
|
+
/** Dedicated only. Seconds before the run is abandoned. */
|
|
615
|
+
timeout?: string | number;
|
|
616
|
+
/** Dedicated only. Retries after a failed run. */
|
|
617
|
+
maxRetry?: string | number;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Hand-authored call-family block statements (U10) — invoking another workspace
|
|
622
|
+
* object from a stack. These carry `!class` transforms in the engine
|
|
623
|
+
* (FunctionRun, FunctionCall, ApiCall, …) so they're authored by hand.
|
|
624
|
+
*
|
|
625
|
+
* Each stores a **cross-object reference** to its target. In a packageExport
|
|
626
|
+
* bundle that reference is the target's guid (the engine's exportTypeId maps a
|
|
627
|
+
* local id → guid on export); xanots resolves the authored target → its
|
|
628
|
+
* deterministic guid via `resolveRef` (see refs/guid.ts), so the emitted call
|
|
629
|
+
* and the target object's payload `guid` agree and the import remaps both.
|
|
630
|
+
*
|
|
631
|
+
* Stored shapes (from the Xano engine's persisted context shapes):
|
|
632
|
+
* function.run → mvp:function ctx { function: { id:<guid> } } [+input]
|
|
633
|
+
* function.call → mvp:workspace_run_function ctx { id:<guid> } [+input]
|
|
634
|
+
* api.call → mvp:workspace_run_endpoint ctx { id:<guid> } [+input]
|
|
635
|
+
* task.call → mvp:workspace_run_task ctx { id:<guid> }
|
|
636
|
+
* tool.call → mvp:workspace_run_tool ctx { id:<guid> } [+input]
|
|
637
|
+
* trigger.call → mvp:workspace_run_trigger ctx { id:<guid> } [+input]
|
|
638
|
+
* middleware.call → mvp:workspace_run_middleware ctx { id:<guid> } [+input]
|
|
639
|
+
* addon.call → mvp:workspace_run_addon ctx { id:<guid> } [+input]
|
|
640
|
+
*
|
|
641
|
+
* The target object's id resolves to a guid keyed by the engine's migrate
|
|
642
|
+
* *type*: function.run/call → "function", api.call → "query" (an API endpoint
|
|
643
|
+
* is a `query` object), and the rest map name-for-name.
|
|
644
|
+
*
|
|
645
|
+
* Scope: connected-service functions are OUT, permanently — they were never
|
|
646
|
+
* released in Xano, so no engine produces the shape and no workspace can hold
|
|
647
|
+
* one. `mvp:function` therefore has exactly one authoring surface, storing the
|
|
648
|
+
* default payload. Async execution IS modelled (see {@link AsyncRuntime});
|
|
649
|
+
* api.call emits the `headers`/`auth` blocks (verb/name/api_group are
|
|
650
|
+
* engine-derived, not stored).
|
|
651
|
+
*
|
|
652
|
+
* @TODO(byte-verify): `function.run` (mvp:function), `api.call` (context.token
|
|
653
|
+
* confirmed tagged), and — since the workflow-test capture — `function.call`
|
|
654
|
+
* (mvp:workspace_run_function) are golden-verified. Still modeled/unverified:
|
|
655
|
+
* - the remaining `workspace_run_*` (task/tool/trigger/middleware/addon) — no
|
|
656
|
+
* golden, but they share the single-key `id` context two goldens now pin.
|
|
657
|
+
* - `workflow_test` → context.{datasource,id} — decode-accurate, no golden.
|
|
658
|
+
* - action / action_package — EXCLUDED from byte-verify: they need an
|
|
659
|
+
* action-identity model first (action id currently resolves via the "function"
|
|
660
|
+
* migrate type, likely wrong; action_package is emitted empty). See their own
|
|
661
|
+
* @TODOs below — do not vendor/capture until the identity model exists.
|
|
662
|
+
*/
|
|
663
|
+
|
|
664
|
+
/** A call/agent `{name: value}` input map — raw scalar literals coerce to constants. */
|
|
665
|
+
type CallInput = Record<string, InputValue>;
|
|
666
|
+
/**
|
|
667
|
+
* A call's target function — a def handle or name, or `null` for the engine's own
|
|
668
|
+
* empty binding (`context.function.id: ""`).
|
|
669
|
+
*
|
|
670
|
+
* ⚠ **Do not author `null`.** It is a BROKEN state in Xano, not a neutral one:
|
|
671
|
+
* the statement calls nothing. It exists so `codegen` can represent a broken
|
|
672
|
+
* statement faithfully rather than degrade it to `raw()` — a pulled `fn: null` is
|
|
673
|
+
* a defect to fix in the pulled workspace, not a shape to copy. Same contract as
|
|
674
|
+
* a db statement's `table` and an addon's, which is where the pattern comes from.
|
|
675
|
+
*/
|
|
676
|
+
type FnRef = ObjectRef | null;
|
|
677
|
+
interface FunctionRunArgs<Fn extends FnRef = FnRef, As extends string = string> extends StatementOptions {
|
|
678
|
+
/** The target function (def handle or name), or `null` when unbound. */
|
|
679
|
+
fn: Fn;
|
|
680
|
+
/** Capture the result into this stack variable. */
|
|
681
|
+
as?: As;
|
|
682
|
+
/** Input bindings, keyed by the target's input names. */
|
|
683
|
+
input?: CallInput;
|
|
684
|
+
/**
|
|
685
|
+
* Run the function in the background instead of inline. Omit for a normal
|
|
686
|
+
* synchronous call. See {@link AsyncRuntime} — an async call does NOT return
|
|
687
|
+
* the function's result.
|
|
688
|
+
*/
|
|
689
|
+
runtime?: AsyncRuntime;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* `function.run <fn>` — run another function inline.
|
|
693
|
+
*
|
|
694
|
+
* Branded `AsShapeBrand<As, InferResponse<Fn>>` (issue #209): the bound variable
|
|
695
|
+
* carries the TARGET's response type, so `ref("<as>.field")` in the caller's
|
|
696
|
+
* response types to that field instead of `unknown`. See {@link functionCall}
|
|
697
|
+
* for what the propagation can and cannot see.
|
|
698
|
+
*
|
|
699
|
+
* An ASYNC run (`runtime`) is deliberately still branded with the function's
|
|
700
|
+
* shape: the engine binds a job handle rather than the result, but `runtime` is
|
|
701
|
+
* an authored value the type system reads as a whole `AsyncRuntime` regardless
|
|
702
|
+
* of what it holds, so narrowing on it would be a guess. Declare `responseShape`
|
|
703
|
+
* on the caller if an async run's binding reaches the response.
|
|
704
|
+
*/
|
|
705
|
+
declare function functionRun<const Fn extends FnRef = FnRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: FunctionRunArgs<Fn, As> & {
|
|
706
|
+
asFilters?: Fs;
|
|
707
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Fn>, Fs>>;
|
|
708
|
+
interface FunctionCallArgs<Fn extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
|
|
709
|
+
fn: Fn;
|
|
710
|
+
as?: As;
|
|
711
|
+
input?: CallInput;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* `function.call <fn>` — invoke a function as a workspace run.
|
|
715
|
+
*
|
|
716
|
+
* Branded `AsShapeBrand<As, InferResponse<Fn>>` (issue #209). `InferResponse` of
|
|
717
|
+
* the TARGET is exactly what a client would get back from it, so drilling into
|
|
718
|
+
* the binding now types:
|
|
719
|
+
*
|
|
720
|
+
* ```ts
|
|
721
|
+
* stack: [s.function.call({ fn: calculateDiscount, input: {…}, as: "discount" })],
|
|
722
|
+
* response: { cents: ref("discount.discount_cents") }, // number, was unknown
|
|
723
|
+
* ```
|
|
724
|
+
*
|
|
725
|
+
* What it can see is what `InferResponse` can see on the target: a declared
|
|
726
|
+
* `responseShape` always, and otherwise the target's own auto-derivation (object
|
|
727
|
+
* literal keys, a variable traced to a typed `db.*`). A target whose response
|
|
728
|
+
* bottoms out at `unknown` — or one named by STRING rather than by def handle,
|
|
729
|
+
* where there is no def to read — propagates that `unknown` unchanged. Declaring
|
|
730
|
+
* `responseShape` on the TARGET fixes every caller at once, which is why that
|
|
731
|
+
* remains the recommendation for a response the walk cannot resolve.
|
|
732
|
+
*/
|
|
733
|
+
declare function functionCall<const Fn extends ObjectRef = ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: FunctionCallArgs<Fn, As> & {
|
|
734
|
+
asFilters?: Fs;
|
|
735
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Fn>, Fs>>;
|
|
736
|
+
interface ApiCallArgs<Api extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
|
|
737
|
+
/** The target API endpoint (a `query` object). */
|
|
738
|
+
api: Api;
|
|
739
|
+
as?: As;
|
|
740
|
+
input?: CallInput;
|
|
741
|
+
/**
|
|
742
|
+
* Replace the request headers the called endpoint sees. Same shape as
|
|
743
|
+
* `s.api.request`'s: a `{ "Name": value }` record (values may be tagged), a
|
|
744
|
+
* `string[]` of full `"Name: value"` lines, or one whole `Value`.
|
|
745
|
+
*
|
|
746
|
+
* ⚠ This is the ONLY slot that authenticates a call with a token computed
|
|
747
|
+
* during the run — an `Authorization` header is read and applied as the
|
|
748
|
+
* caller's token, while `auth.token` is a static string (see {@link ApiCallArgs.auth}):
|
|
749
|
+
*
|
|
750
|
+
* ```ts
|
|
751
|
+
* s.api.call({ api: signup, input: {…}, as: "signup" }),
|
|
752
|
+
* s.api.call({ api: checkout, headers: { Authorization: ref("signup.authToken") } }),
|
|
753
|
+
* ```
|
|
754
|
+
*
|
|
755
|
+
* Send `Authorization` only to an endpoint that declares `auth` — the engine
|
|
756
|
+
* enforces that the token's table matches the target's, and a target with no
|
|
757
|
+
* `auth` rejects any token as belonging to a different object type.
|
|
758
|
+
*/
|
|
759
|
+
headers?: readonly string[] | HeaderMap | Value;
|
|
760
|
+
/**
|
|
761
|
+
* Authenticate the call with a STATIC token, and optionally ignore its expiry.
|
|
762
|
+
*
|
|
763
|
+
* ⚠ `token` is stored in a slot the engine declares as plain text and does NOT
|
|
764
|
+
* evaluate, so a tagged `Value` — `ref("signup.authToken")`, `env("TOKEN")` —
|
|
765
|
+
* is rejected at runtime with `Param: token - Text filter requires an integer,
|
|
766
|
+
* float, string or boolean value`, even though it deploys clean. Only a bare
|
|
767
|
+
* **string** runs. For a token minted during the run, use an `Authorization`
|
|
768
|
+
* entry in {@link ApiCallArgs.headers} instead.
|
|
769
|
+
*
|
|
770
|
+
* The `Value` spelling stays accepted so a pulled workspace holding one
|
|
771
|
+
* round-trips as itself (issue #139) — it is a shape to carry, not to author.
|
|
772
|
+
*/
|
|
773
|
+
auth?: {
|
|
774
|
+
token: Value | string;
|
|
775
|
+
ignoreExpiration?: boolean;
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* `api.call <endpoint>` — invoke an API endpoint as a workspace run. The stored
|
|
780
|
+
* `context` is `{ id, headers?, token?, token_ignore_expiration? }` (the engine
|
|
781
|
+
* derives name/verb/api_group from the referenced query at encode time, so they
|
|
782
|
+
* are intentionally NOT stored). Shape modeled on the engine's stored api-call format.
|
|
783
|
+
*
|
|
784
|
+
* `context.headers` is a tagged value the engine EVALUATES, so it carries a
|
|
785
|
+
* runtime-computed `Authorization`. `context.token` is not: the engine declares
|
|
786
|
+
* that slot as plain text, so a tagged token round-trips byte-for-byte (the
|
|
787
|
+
* golden pins that) and is then rejected the moment the statement runs. See
|
|
788
|
+
* {@link ApiCallArgs.auth}.
|
|
789
|
+
*/
|
|
790
|
+
declare function apiCall<const Api extends ObjectRef = ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: ApiCallArgs<Api, As> & {
|
|
791
|
+
asFilters?: Fs;
|
|
792
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Api>, Fs>>;
|
|
793
|
+
interface TaskCallArgs extends StatementOptions {
|
|
794
|
+
/** The target background task. */
|
|
795
|
+
task: ObjectRef;
|
|
796
|
+
as?: string;
|
|
797
|
+
}
|
|
798
|
+
/** `task.call <task>` — invoke a task as a workspace run (no input). */
|
|
799
|
+
declare function taskCall(args: TaskCallArgs): Statement;
|
|
800
|
+
interface ToolCallArgs<Tool extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
|
|
801
|
+
tool: Tool;
|
|
802
|
+
as?: As;
|
|
803
|
+
input?: CallInput;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* `tool.call <tool>` — invoke a tool as a workspace run. Branded with the
|
|
807
|
+
* TARGET's `InferResponse` (issue #209), like {@link functionCall}.
|
|
808
|
+
*/
|
|
809
|
+
declare function toolCall<const Tool extends ObjectRef = ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: ToolCallArgs<Tool, As> & {
|
|
810
|
+
asFilters?: Fs;
|
|
811
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Tool>, Fs>>;
|
|
812
|
+
interface TriggerCallArgs extends StatementOptions {
|
|
813
|
+
trigger: ObjectRef;
|
|
814
|
+
as?: string;
|
|
815
|
+
input?: CallInput;
|
|
816
|
+
}
|
|
817
|
+
/** `trigger.call <trigger>` — invoke a trigger as a workspace run. */
|
|
818
|
+
declare function triggerCall(args: TriggerCallArgs): Statement;
|
|
819
|
+
interface MiddlewareCallArgs extends StatementOptions {
|
|
820
|
+
middleware: ObjectRef;
|
|
821
|
+
as?: string;
|
|
822
|
+
input?: CallInput;
|
|
823
|
+
}
|
|
824
|
+
/** `middleware.call <middleware>` — invoke middleware as a workspace run. */
|
|
825
|
+
declare function middlewareCall(args: MiddlewareCallArgs): Statement;
|
|
826
|
+
interface AddonCallArgs extends StatementOptions {
|
|
827
|
+
addon: ObjectRef;
|
|
828
|
+
as?: string;
|
|
829
|
+
input?: CallInput;
|
|
830
|
+
}
|
|
831
|
+
/** `addon.call <addon>` — invoke an addon as a workspace run. */
|
|
832
|
+
declare function addonCall(args: AddonCallArgs): Statement;
|
|
833
|
+
interface ActionCallArgs extends StatementOptions {
|
|
834
|
+
/** The action's name. */
|
|
835
|
+
action: ObjectRef;
|
|
836
|
+
/** The action package identifier. */
|
|
837
|
+
package?: string;
|
|
838
|
+
as?: string;
|
|
839
|
+
input?: CallInput;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* `action.call <action>` — invoke a marketplace/action operation (`mvp:action`).
|
|
843
|
+
* Stored shape from the engine's action-call format: `context.run_version.id` is the action
|
|
844
|
+
* id and `settings_registry` is always present.
|
|
845
|
+
*
|
|
846
|
+
* @TODO(byte-verify): xanots has no `action` kind, so the id resolves via the
|
|
847
|
+
* "function" migrate type — likely WRONG (actions are a distinct namespace,
|
|
848
|
+
* `mapActionNameToId`). input[] uses the lean shape; the engine uses
|
|
849
|
+
* `convertBlockToInput` (may be the rich form). No golden.
|
|
850
|
+
*/
|
|
851
|
+
declare function actionCall(args: ActionCallArgs): Statement;
|
|
852
|
+
/**
|
|
853
|
+
* `action.package.call <action>` — invoke an action-package operation
|
|
854
|
+
* (`mvp:action_package`). Stored shape from the engine's action-package format:
|
|
855
|
+
* `context.{action:{trace_id}, package:{slug}, package_version:{id}}`.
|
|
856
|
+
*
|
|
857
|
+
* @TODO(byte-verify): MODELED skeleton only — xanots doesn't model marketplace
|
|
858
|
+
* action packages (trace_id / package slug / version id come from
|
|
859
|
+
* `mapActionPackageNameToId`), so these are emitted EMPTY. This statement is a
|
|
860
|
+
* reachable placeholder, NOT functional, until the action-package identity model
|
|
861
|
+
* exists. No golden.
|
|
862
|
+
*/
|
|
863
|
+
declare function actionPackageCall(args: ActionCallArgs): Statement;
|
|
864
|
+
interface WorkflowTestCallArgs extends StatementOptions {
|
|
865
|
+
/** The target workflow test. */
|
|
866
|
+
workflowTest: ObjectRef;
|
|
867
|
+
as?: string;
|
|
868
|
+
/** Data source to run against. */
|
|
869
|
+
datasource?: string;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* `workflow_test.call <test>` — run a workflow test
|
|
873
|
+
* (`mvp:workspace_run_workflow_test`). Stored shape from the engine's workflow-test format:
|
|
874
|
+
* `context.{datasource, id}` — `datasource` is ALWAYS present (default `""`).
|
|
875
|
+
*/
|
|
876
|
+
declare function workflowTestCall(args: WorkflowTestCallArgs): Statement;
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Hand-authored AI-agent and cloud-job specials (U10). All carry `!class`
|
|
880
|
+
* transforms in the engine (AgentRun, CloudJob, CloudJobAwait, CloudJobStatus).
|
|
881
|
+
* The stored shapes here are modeled on those transforms' `decode()` methods
|
|
882
|
+
* (authoritative for the persisted form), so they're grounded — but still have
|
|
883
|
+
* no golden fixture to deep-equal against.
|
|
884
|
+
*
|
|
885
|
+
* call_agent and cloud_job{,_await,_status} are golden-verified against live
|
|
886
|
+
* engine captures (see the conformance corpus): agent → context.toolset.id +
|
|
887
|
+
* top-level runtime + input[]; cloud jobs → everything in input[] with the
|
|
888
|
+
* captured entry order. `runtime` is omitted at the default "shared" mode, and
|
|
889
|
+
* `await` is passed through as authored.
|
|
890
|
+
*/
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* The rich result object an agent run binds to its `as` variable — modeled on
|
|
894
|
+
* the engine's agent-run result envelope (issue #89). **The completion is at
|
|
895
|
+
* `.result`**, not the top level; the surrounding fields are run metadata.
|
|
896
|
+
*
|
|
897
|
+
* `R` is the completion type: `string` for a text agent (the default — including
|
|
898
|
+
* `xano-free`), or an object when structured outputs (a schema) are enabled. When
|
|
899
|
+
* the run targets an agent *handle* it is inferred from that agent's `output.schema`
|
|
900
|
+
* automatically; the `resultShape` witness on {@link AiAgentRunArgs} overrides it.
|
|
901
|
+
*
|
|
902
|
+
* `finishReasonCandidate`/`toolCalls`/`usage`/`totalUsage` are optional: they are
|
|
903
|
+
* absent or empty depending on the run (no tools, single provider, engine
|
|
904
|
+
* version), so a returned envelope may carry only a subset.
|
|
905
|
+
*/
|
|
906
|
+
interface AgentRunResult<R = string> {
|
|
907
|
+
/** The model's completion — the field almost every caller wants. `string` unless structured outputs are enabled (then an object, inferred from the agent's `output.schema`). */
|
|
908
|
+
result: R;
|
|
909
|
+
/** Why generation stopped: `'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other' | 'unknown'`. */
|
|
910
|
+
finishReason: string;
|
|
911
|
+
/** Provider-specific metadata (e.g. usage counters, safety signals), keyed by provider. */
|
|
912
|
+
providerMetadata: Record<string, Record<string, unknown>>;
|
|
913
|
+
/** Reasoning parts emitted by the model; `[]` when none. */
|
|
914
|
+
reasoningDetails: unknown[];
|
|
915
|
+
/** Per-step records (each with e.g. `text`, `finishReason`, `usage`, `toolCalls`, `providerMetadata`). */
|
|
916
|
+
steps: unknown[];
|
|
917
|
+
/** Fallback finish reason, populated only when `finishReason` is `'unknown'`; otherwise empty/absent. */
|
|
918
|
+
finishReasonCandidate?: string;
|
|
919
|
+
/** Merged tool-call + result records; absent or empty when no tools ran. */
|
|
920
|
+
toolCalls?: unknown[];
|
|
921
|
+
/** Token usage for the final generation (`inputTokens`, `outputTokens`, `totalTokens`, …). */
|
|
922
|
+
usage?: Record<string, unknown>;
|
|
923
|
+
/** Token usage aggregated across all steps. */
|
|
924
|
+
totalUsage?: Record<string, unknown>;
|
|
925
|
+
}
|
|
926
|
+
interface AiAgentRunArgs<As extends string = "", A extends ObjectRef = ObjectRef, R = AgentResultOf<A>> extends StatementOptions {
|
|
927
|
+
/** The target agent (toolset of type agent — def handle or name). */
|
|
928
|
+
agent: A;
|
|
929
|
+
/** The stack variable this run binds. Captured literally so `InferResponse` can trace a `ref` back to the typed {@link AgentRunResult}. */
|
|
930
|
+
as?: As;
|
|
931
|
+
/**
|
|
932
|
+
* Run arguments passed to the agent. Pass a single {@link Value}, or an object
|
|
933
|
+
* literal of values (`{ question: inp("question") }`) which is built into a
|
|
934
|
+
* dynamic object via {@link obj}. This becomes the agent's `$args` Twig
|
|
935
|
+
* namespace: the agent's string settings (system prompt, prompt, model,
|
|
936
|
+
* provider config) reference these as `{{ $args.propertyName }}`, resolved per
|
|
937
|
+
* invocation before the LLM call. (Env vars are `{{ $env.NAME }}`.) See
|
|
938
|
+
* `kinds/agent.ts` for the full templating rules.
|
|
939
|
+
*/
|
|
940
|
+
args?: Value | ObjInput;
|
|
941
|
+
/** Whether the agent may execute its tools. */
|
|
942
|
+
allowToolExecution?: Value;
|
|
943
|
+
/** Pinned agent version. */
|
|
944
|
+
version?: Value;
|
|
945
|
+
/**
|
|
946
|
+
* Run the agent in the background instead of inline. Omit for a normal
|
|
947
|
+
* synchronous call. Shares {@link AsyncRuntime} with `function.run` — the
|
|
948
|
+
* engine reads the same top-level block for both.
|
|
949
|
+
*/
|
|
950
|
+
runtime?: AsyncRuntime;
|
|
951
|
+
/**
|
|
952
|
+
* Type-only override for the `.result` completion type. Usually unnecessary:
|
|
953
|
+
* when `agent` is a def handle from `agent({ output: { schema } })`, `.result`
|
|
954
|
+
* is inferred straight from that schema via {@link AgentResultOf} (issue
|
|
955
|
+
* #124.1). Pass a witness only to override that inference or to type the
|
|
956
|
+
* `.result` of an agent referenced by bare name (which carries no schema) —
|
|
957
|
+
* e.g. `resultShape: {} as { sentiment: string }`. Never emitted into the
|
|
958
|
+
* statement (phantom, like the response brand).
|
|
959
|
+
*/
|
|
960
|
+
resultShape?: R;
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* `ai.agent.run <agent>` — invoke an AI agent (`mvp:call_agent`). Stored shape
|
|
964
|
+
* from the engine's agent-run format: the target is `context.toolset.id`, `runtime` is a
|
|
965
|
+
* TOP-LEVEL `{ mode }` block, and `args`/`allow_tool_execution`/`version` are
|
|
966
|
+
* `input[]` entries (NOT context). `runtime` is emitted only when a mode is set.
|
|
967
|
+
*
|
|
968
|
+
* Branded with `AsShapeBrand<As, AgentRunResult<R>>` (like the `db.*` producers)
|
|
969
|
+
* so `ref(as)` traces to the typed {@link AgentRunResult} envelope via
|
|
970
|
+
* `InferResponse` instead of `unknown` — the completion is at `.result` (#89).
|
|
971
|
+
* A dotted `ref("<as>.result")` now projects that completion directly (#93), so
|
|
972
|
+
* the common "return just the answer" endpoint no longer needs a `responseShape`.
|
|
973
|
+
* The brand is phantom; the emitted statement bytes are unchanged.
|
|
974
|
+
*/
|
|
975
|
+
declare function aiAgentRun<const As extends string = "", const A extends ObjectRef = ObjectRef, R = AgentResultOf<A>, const Fs extends readonly FilterXdo[] = readonly []>(a: AiAgentRunArgs<As, A, R> & {
|
|
976
|
+
asFilters?: Fs;
|
|
977
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<AgentRunResult<R>, Fs>>;
|
|
978
|
+
interface CloudJobArgs extends StatementOptions {
|
|
979
|
+
as?: string;
|
|
980
|
+
image?: Value;
|
|
981
|
+
command?: Value;
|
|
982
|
+
args?: Value;
|
|
983
|
+
secret?: Value;
|
|
984
|
+
template?: Value;
|
|
985
|
+
/** Seconds to await completion (default 60). */
|
|
986
|
+
await?: Value;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* `cloud.job { … }` — launch a containerized cloud job (`mvp:cloud_job`). Stored
|
|
990
|
+
* shape from the engine's cloud-job format: every block (image/command/args/secret/template/
|
|
991
|
+
* await) is an `input[]` entry; `context` is empty.
|
|
992
|
+
*
|
|
993
|
+
* Golden-verified against a live capture: the input[] entry order
|
|
994
|
+
* (image→command→args→secret→template→await) matches the persisted shape.
|
|
995
|
+
*/
|
|
996
|
+
declare function cloudJob(a: CloudJobArgs): Statement;
|
|
997
|
+
interface CloudJobAwaitArgs extends StatementOptions {
|
|
998
|
+
as?: string;
|
|
999
|
+
/** Job ids to await. */
|
|
1000
|
+
ids: Value;
|
|
1001
|
+
/** Timeout in seconds. */
|
|
1002
|
+
timeout: Value;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* `cloud.job.await { … }` — wait for cloud jobs to finish (`mvp:cloud_job_await`).
|
|
1006
|
+
* `ids`/`timeout` are `input[]` entries with empty context (per the engine's cloud-job-await format).
|
|
1007
|
+
*/
|
|
1008
|
+
declare function cloudJobAwait(a: CloudJobAwaitArgs): Statement;
|
|
1009
|
+
interface CloudJobStatusArgs extends StatementOptions {
|
|
1010
|
+
as?: string;
|
|
1011
|
+
/** The job id to query. */
|
|
1012
|
+
id: Value;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* `cloud.job.status { … }` — read a cloud job's status (`mvp:cloud_job_status`).
|
|
1016
|
+
* `id` is an `input[]` entry with empty context (per the engine's cloud-job-status format).
|
|
1017
|
+
*/
|
|
1018
|
+
declare function cloudJobStatus(a: CloudJobStatusArgs): Statement;
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Hand-authored miscellaneous specials (U10) — the remaining `!class` /
|
|
1022
|
+
* `!function` / declarative statements without a generated factory: array
|
|
1023
|
+
* map/union, the comment & placeholder nodes, raw-input access, post-process,
|
|
1024
|
+
* realtime events, auth-token creation, and the `expect.to_throw` test
|
|
1025
|
+
* assertion.
|
|
1026
|
+
*
|
|
1027
|
+
* `comment`, `realtime_event`, and `create_auth` have declarative transforms in
|
|
1028
|
+
* the engine schema and are encoded to match them; the rest are `!class` with no
|
|
1029
|
+
* persisted golden yet, so they are **structural** (reachable, byte-verified
|
|
1030
|
+
* later). Block fields map to same-named `context` entries unless the schema's
|
|
1031
|
+
* declarative transform says otherwise.
|
|
1032
|
+
*
|
|
1033
|
+
* array_map, array_union, get_input, and test_expect_to_throw are now
|
|
1034
|
+
* golden-verified against live engine captures (see the conformance corpus);
|
|
1035
|
+
* post_process is parser-verified. Remaining unverified spots:
|
|
1036
|
+
* (1) array_map — the scalar `transform_value` path is byte-exact. The
|
|
1037
|
+
* object-literal form (`transform_object` + `output_type:"object"`) is now
|
|
1038
|
+
* authorable and round-trips through codegen, but is modeled from the
|
|
1039
|
+
* engine's declared context schema rather than a capture: no golden yet.
|
|
1040
|
+
* (2) create_auth — input order is `id/dbtable/extras/expiration`, read from the
|
|
1041
|
+
* engine's own input schema; `extras`/`expiration` are `?=` optionals and
|
|
1042
|
+
* are omitted when unset. Only the `dbtable` const tag is unverified.
|
|
1043
|
+
* (3) realtime_event — context.{channel,data,auth.{dbo_id,row_id}} CONFIRMED by
|
|
1044
|
+
* the schema transform (auth_table via !map:dbo:constant → table guid).
|
|
1045
|
+
*/
|
|
1046
|
+
|
|
1047
|
+
interface ArrayMapArgs extends StatementOptions {
|
|
1048
|
+
/** The source array → stored `collection`. */
|
|
1049
|
+
source: Value;
|
|
1050
|
+
as?: string;
|
|
1051
|
+
/**
|
|
1052
|
+
* How each item maps. Three forms, and the form picks the engine's `output_type`:
|
|
1053
|
+
* - a single {@link Value} → each item maps to that scalar expression
|
|
1054
|
+
* (`output_type:"value"`, stored `transform_value`);
|
|
1055
|
+
* - a record of values → each item maps to an OBJECT with those keys
|
|
1056
|
+
* (`output_type:"object"`, stored `transform_object[]`);
|
|
1057
|
+
* - a list of `{key, value}` pairs → the same object form, for the keys a
|
|
1058
|
+
* record cannot hold: one the engine COMPUTES per item, or two rows sharing
|
|
1059
|
+
* a key (see {@link ArrayMapAttribute}).
|
|
1060
|
+
*
|
|
1061
|
+
* Use `ref("$this")` for the current item and `ref("$index")` for its position.
|
|
1062
|
+
* An empty record is rejected — the engine's object branch iterates
|
|
1063
|
+
* `transform_object` and would map every item to `{}`.
|
|
1064
|
+
*/
|
|
1065
|
+
transform?: Value | Record<string, Value> | ArrayMapAttribute[];
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* One key/value pair of an object transform, for the shapes a record cannot
|
|
1069
|
+
* hold.
|
|
1070
|
+
*
|
|
1071
|
+
* The engine evaluates `attribute_key` per item exactly as it evaluates the
|
|
1072
|
+
* value, so a key can be a variable, an input, or a filtered expression — and
|
|
1073
|
+
* two rows may carry the SAME key, which a record would silently collapse to
|
|
1074
|
+
* the last one. Reach for the record form whenever the keys are plain literals;
|
|
1075
|
+
* it is what an ordinary object mapping should read like.
|
|
1076
|
+
*/
|
|
1077
|
+
interface ArrayMapAttribute {
|
|
1078
|
+
/** The key this row contributes, evaluated per item. */
|
|
1079
|
+
key: Value;
|
|
1080
|
+
/** The value stored under it. */
|
|
1081
|
+
value: Value;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* `array.map <source>` — map each element through an expression (`mvp:array_map`).
|
|
1085
|
+
*
|
|
1086
|
+
* Both engine output modes are golden-verified against live captures. The object
|
|
1087
|
+
* path (`output_type:"object"` + `transform_object[]`) stores one
|
|
1088
|
+
* `{attribute_key, attribute_value}` entry per record key, in authored order,
|
|
1089
|
+
* and the key is a plain `const` text triple.
|
|
1090
|
+
*
|
|
1091
|
+
* Only the LIVE branch is emitted, and the capture confirms the engine agrees:
|
|
1092
|
+
* an imported object-mode statement stores NO `transform_value`, and a
|
|
1093
|
+
* value-mode one stores no `transform_object`. The EDITOR is the exception — it
|
|
1094
|
+
* builds its form from the whole context schema and saves every control, so an
|
|
1095
|
+
* editor-saved object-mode statement also carries `transform_value` at its
|
|
1096
|
+
* schema defaults. Both spellings are one state (the engine's object branch
|
|
1097
|
+
* never reads `transform_value`); `liveArrayMapContext` in validate/normalize.ts
|
|
1098
|
+
* is where that equivalence lives, so an editor-authored statement still reads
|
|
1099
|
+
* back to this factory instead of falling to `raw()`.
|
|
1100
|
+
*
|
|
1101
|
+
* ```ts
|
|
1102
|
+
* // scalar: ["a","b"] → ["A","B"]
|
|
1103
|
+
* s.array.map({ source: ref("names"), as: "upper", transform: withFilters(ref("$this"), fl.upper()) })
|
|
1104
|
+
* // object: [1,2] → [{id:1, pos:0}, {id:2, pos:1}]
|
|
1105
|
+
* s.array.map({ source: ref("ids"), as: "rows", transform: { id: ref("$this"), pos: ref("$index") } })
|
|
1106
|
+
* ```
|
|
1107
|
+
*/
|
|
1108
|
+
declare function arrayMap(a: ArrayMapArgs): Statement;
|
|
1109
|
+
interface ArrayUnionArgs extends StatementOptions {
|
|
1110
|
+
/** The base array → stored `left`. */
|
|
1111
|
+
source: Value;
|
|
1112
|
+
/** The array to union in → stored `right`. */
|
|
1113
|
+
with?: Value;
|
|
1114
|
+
as?: string;
|
|
1115
|
+
/** Optional per-item transform → stored `transform_value`. */
|
|
1116
|
+
transform?: Value;
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* `array.union <source>` — set-union of arrays (`mvp:array_union`).
|
|
1120
|
+
*
|
|
1121
|
+
* Golden-verified against a live capture: the field remap (source→left,
|
|
1122
|
+
* with→right, transform→transform_value) matches the engine's array-union format.
|
|
1123
|
+
*/
|
|
1124
|
+
declare function arrayUnion(a: ArrayUnionArgs): Statement;
|
|
1125
|
+
/**
|
|
1126
|
+
* `comment` — a no-op annotation node (`mvp:comment`). The text IS this
|
|
1127
|
+
* statement's `description`, so `text` and `a.description` set the same member
|
|
1128
|
+
* and an explicit `a.description` wins; `a.disabled` applies as it does anywhere.
|
|
1129
|
+
*/
|
|
1130
|
+
declare function comment(text?: string, a?: StatementAnnotations): Statement;
|
|
1131
|
+
interface GetRawInputArgs extends StatementOptions {
|
|
1132
|
+
as?: string;
|
|
1133
|
+
/** Body decoding (`json`, `raw`, …). */
|
|
1134
|
+
encoding?: Value;
|
|
1135
|
+
/** Skip middleware-applied transforms. */
|
|
1136
|
+
excludeMiddleware?: Value;
|
|
1137
|
+
}
|
|
1138
|
+
/**
|
|
1139
|
+
* `util.get_raw_input` / `util.get_input` — capture the raw request body
|
|
1140
|
+
* (`mvp:get_input`). Empty context, and up to two `input[]` entries — `encoding`
|
|
1141
|
+
* (`?=json`) and `exclude_middleware_modification` (note the full stored name;
|
|
1142
|
+
* `?=false`). Both are optional in the engine schema and are written only when
|
|
1143
|
+
* authored, matching what Xano's editor stores.
|
|
1144
|
+
*/
|
|
1145
|
+
declare function getRawInput(a?: GetRawInputArgs): Statement;
|
|
1146
|
+
/**
|
|
1147
|
+
* `util.post_process { … }` — run a post-response sub-stack (`mvp:post_process`).
|
|
1148
|
+
* A pure block statement (engine schema `args: []`): no `as`, just the `run`
|
|
1149
|
+
* stack. Byte-verified (parser-minimal) against the engine's persisted shape.
|
|
1150
|
+
*/
|
|
1151
|
+
declare function postProcess(body: Statement[], a?: StatementAnnotations): Statement;
|
|
1152
|
+
interface RealtimeEventArgs extends StatementAnnotations {
|
|
1153
|
+
/** The channel to publish on. */
|
|
1154
|
+
channel: Value;
|
|
1155
|
+
/** The event payload. */
|
|
1156
|
+
data: Value;
|
|
1157
|
+
/** Optional auth table whose row scopes the event. */
|
|
1158
|
+
authTable?: ObjectRef;
|
|
1159
|
+
/** The auth row id. */
|
|
1160
|
+
authId: Value;
|
|
1161
|
+
}
|
|
1162
|
+
/**
|
|
1163
|
+
* `api.realtime_event { … }` — publish a realtime event (`mvp:realtime_event`).
|
|
1164
|
+
*
|
|
1165
|
+
* @deprecated Superseded by {@link realtimePublish}. This publishes to Xano's older
|
|
1166
|
+
* workspace-global realtime layer, NOT to a `realtimeChannel()` — its `channel` is a
|
|
1167
|
+
* string against that layer, so pointing it at a current-layer channel path publishes
|
|
1168
|
+
* into the void.
|
|
1169
|
+
*
|
|
1170
|
+
* To originate an event on the current layer, use `s.realtime.publish`, which names the
|
|
1171
|
+
* owning `realtimeServer()` and so addresses a real `realtimeChannel()`.
|
|
1172
|
+
*
|
|
1173
|
+
* Still exported and still supported so `xanots codegen` can bring back a workspace
|
|
1174
|
+
* that holds one. Withheld from the `llms.txt` statement catalog and named only under
|
|
1175
|
+
* `llms/legacy.md`.
|
|
1176
|
+
*/
|
|
1177
|
+
declare function realtimeEvent(a: RealtimeEventArgs): Statement;
|
|
1178
|
+
/**
|
|
1179
|
+
* The realtime server to publish onto: a `realtimeServer()` handle, its bare name, or
|
|
1180
|
+
* a `Value` when the name is computed at runtime.
|
|
1181
|
+
*
|
|
1182
|
+
* The engine resolves this server by NAME within the current workspace and branch —
|
|
1183
|
+
* not by guid — so a handle contributes its `name`, not its identity.
|
|
1184
|
+
*/
|
|
1185
|
+
type RealtimePublishServer = string | {
|
|
1186
|
+
name: string;
|
|
1187
|
+
} | Value;
|
|
1188
|
+
interface RealtimePublishArgs extends StatementAnnotations {
|
|
1189
|
+
/**
|
|
1190
|
+
* The owning realtime server, by name. Required: a channel path is unique only
|
|
1191
|
+
* within its server, so the path alone cannot be addressed.
|
|
1192
|
+
*/
|
|
1193
|
+
server: RealtimePublishServer;
|
|
1194
|
+
/**
|
|
1195
|
+
* The channel PATH to publish onto, already filled in — `c.text("rooms/42")`, not
|
|
1196
|
+
* the `rooms/{room_id}` template. Build it with `realtimeChannel().getChannel({…})`
|
|
1197
|
+
* rather than concatenating by hand.
|
|
1198
|
+
*/
|
|
1199
|
+
channel: Value;
|
|
1200
|
+
/** The event payload delivered to subscribers. */
|
|
1201
|
+
data: Value;
|
|
1202
|
+
/**
|
|
1203
|
+
* Optional message TYPE stamped on the frame, so a client that switches on type can
|
|
1204
|
+
* route a server-originated event the same way it routes a `realtimeMessage()` one.
|
|
1205
|
+
* Naming a type does NOT invoke that message's handler — see the note on delivery below.
|
|
1206
|
+
*/
|
|
1207
|
+
message?: Value;
|
|
1208
|
+
/**
|
|
1209
|
+
* Optional ASSERTED identity attributed to the event: name an auth **table** (a
|
|
1210
|
+
* `table({ auth: true })` def or its name) and it resolves to that table's guid.
|
|
1211
|
+
*
|
|
1212
|
+
* This is attribution carried on the frame, NOT a credential — nothing validates it
|
|
1213
|
+
* and no auth gate consumes it. Do not use it to grant a publish that a channel's
|
|
1214
|
+
* `publish.who` would otherwise refuse; this statement bypasses that gate entirely.
|
|
1215
|
+
*/
|
|
1216
|
+
authTable?: ObjectRef;
|
|
1217
|
+
/** The asserted identity's row id. Attribution only — see {@link RealtimePublishArgs.authTable}. */
|
|
1218
|
+
authId?: Value;
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* `realtime.publish { … }` — originate a server-authored event onto a realtime channel
|
|
1222
|
+
* from any function stack (`mvp:realtime_publish`).
|
|
1223
|
+
*
|
|
1224
|
+
* This is how a query, task, function, or trigger pushes to connected clients without a
|
|
1225
|
+
* client frame arriving first: "the auction closed", "the job finished", "row 42 changed".
|
|
1226
|
+
*
|
|
1227
|
+
* Three properties decide whether this is the right tool, and all three surprise people:
|
|
1228
|
+
*
|
|
1229
|
+
* - **Delivery-only.** The event is fanned out to subscribers as-is. It does NOT invoke
|
|
1230
|
+
* a `realtimeMessage()` handler, even when `message` names one, so no stack of yours
|
|
1231
|
+
* runs on the delivery side. A channel `deliver` trigger still applies (it belongs to
|
|
1232
|
+
* the channel, not to the message).
|
|
1233
|
+
* - **Server-authoritative.** It bypasses the channel's `publish.who` policy — that gate
|
|
1234
|
+
* governs CLIENTS. Any stack that can run this can publish, so guard it in your own
|
|
1235
|
+
* stack if that matters.
|
|
1236
|
+
* - **Fail-soft.** A missing or disabled server, a server with no minted canonical, or an
|
|
1237
|
+
* unreachable bus is logged engine-side and returns quietly. NOTHING throws into your
|
|
1238
|
+
* stack and there is no return value to check, so a mis-targeted publish is SILENT.
|
|
1239
|
+
* The two references this SDK can check — `server` and `channel` — throw here at author
|
|
1240
|
+
* time instead, because that is the only loud failure available.
|
|
1241
|
+
*
|
|
1242
|
+
* It does not rescue `deliverTo: "explicit"` on a `realtimeMessage()`: this originates an
|
|
1243
|
+
* event INTO a channel and never selects recipients from inside a handler.
|
|
1244
|
+
*
|
|
1245
|
+
* ```ts
|
|
1246
|
+
* const rooms = realtimeChannel({ name: "rooms/{room_id}", server: chat, input: { room_id: input.int() } });
|
|
1247
|
+
* s.realtime.publish({
|
|
1248
|
+
* server: chat,
|
|
1249
|
+
* channel: c.text(rooms.getChannel({ room_id: 42 })),
|
|
1250
|
+
* message: c.text("post"),
|
|
1251
|
+
* data: obj({ body: "the auction closed" }),
|
|
1252
|
+
* });
|
|
1253
|
+
* ```
|
|
1254
|
+
*/
|
|
1255
|
+
declare function realtimePublish(a: RealtimePublishArgs): Statement;
|
|
1256
|
+
interface CreateAuthTokenArgs<As extends string = string> extends StatementOptions {
|
|
1257
|
+
/**
|
|
1258
|
+
* The auth table the token authenticates against.
|
|
1259
|
+
*
|
|
1260
|
+
* `null` is the UNBOUND table the engine stores as a blank guid — deleted, or
|
|
1261
|
+
* never bound. It exists so `codegen` can reproduce such a statement instead
|
|
1262
|
+
* of throwing, the same "no target" spelling `db.query`'s `table` carries.
|
|
1263
|
+
*/
|
|
1264
|
+
table: ObjectRef | null;
|
|
1265
|
+
/** Token id (the authenticated row id). */
|
|
1266
|
+
id: Value;
|
|
1267
|
+
/** Extra claims embedded in the token. Defaults to `{}` (no extra claims). */
|
|
1268
|
+
extras?: Value;
|
|
1269
|
+
/** Expiry in seconds. Defaults to `86400` (24h); `0` never expires. */
|
|
1270
|
+
expiration?: Value;
|
|
1271
|
+
as?: As;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* `security.create_auth_token { … }` — mint an auth token (`mvp:create_auth`).
|
|
1275
|
+
*
|
|
1276
|
+
* Branded `AsShapeBrand<As, string>` (like the `db.*` producers) so a
|
|
1277
|
+
* `ref("<as>")` to the minted token traces to `string` via `InferResponse`
|
|
1278
|
+
* instead of `unknown` — the token is always a JWT string. The brand is phantom;
|
|
1279
|
+
* the emitted statement bytes are unchanged.
|
|
1280
|
+
*/
|
|
1281
|
+
declare function createAuthToken<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a: CreateAuthTokenArgs<As> & {
|
|
1282
|
+
asFilters?: Fs;
|
|
1283
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<string, Fs>>;
|
|
1284
|
+
/**
|
|
1285
|
+
* `security.create_guid` — generate a GUID (`mvp:guid`).
|
|
1286
|
+
*
|
|
1287
|
+
* The engine's statement declares no context, input, or output schema at all
|
|
1288
|
+
* (`Generate GUID`): it takes nothing and binds the generated value, so `as` is
|
|
1289
|
+
* the only thing to author. Sibling of `security.create_uuid` (`mvp:uuid4`),
|
|
1290
|
+
* which is a different generator and a different stored statement — the SDK
|
|
1291
|
+
* models both rather than folding one into the other.
|
|
1292
|
+
*
|
|
1293
|
+
* Branded `AsShapeBrand<As, string>` so a `ref("<as>")` traces to `string`.
|
|
1294
|
+
*/
|
|
1295
|
+
declare function createGuid<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a?: {
|
|
1296
|
+
as?: As;
|
|
1297
|
+
} & StatementOptions & {
|
|
1298
|
+
asFilters?: Fs;
|
|
1299
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<string, Fs>>;
|
|
1300
|
+
interface ExpectToThrowArgs extends StatementAnnotations {
|
|
1301
|
+
/** The statements expected to raise. */
|
|
1302
|
+
body: Statement[];
|
|
1303
|
+
/**
|
|
1304
|
+
* Text the raised error's message must CONTAIN (case-insensitive substring).
|
|
1305
|
+
* Omit to accept any error.
|
|
1306
|
+
*/
|
|
1307
|
+
exception?: Value;
|
|
1308
|
+
}
|
|
1309
|
+
/**
|
|
1310
|
+
* `expect.to_throw { … }` — assert a sub-stack throws (`mvp:test_expect_to_throw`).
|
|
1311
|
+
*
|
|
1312
|
+
* The matcher is stored as `context.value1` — the numbered slot every
|
|
1313
|
+
* `expect.*` statement keeps its operands in. It was emitted as
|
|
1314
|
+
* `context.exception` through 2.0.21, a key the engine never reads, so a
|
|
1315
|
+
* to_throw carrying one accepted ANY error instead of the one named (issue #228).
|
|
1316
|
+
*/
|
|
1317
|
+
declare function expectToThrow(a: ExpectToThrowArgs): Statement;
|
|
1318
|
+
interface ExpectToMatchArgs extends StatementAnnotations {
|
|
1319
|
+
/** The value under test — the SUBJECT the pattern is matched against. */
|
|
1320
|
+
expr?: Value;
|
|
1321
|
+
/** The regex PATTERN. Build it with `c.regex(...)`, not `c.text(...)`. */
|
|
1322
|
+
value?: Value;
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* `expect.to_match` — assert a value matches a regex (`mvp:test_expect_to_match`).
|
|
1326
|
+
*
|
|
1327
|
+
* A typed, guarded pass-through to the generated factory: same bytes, same
|
|
1328
|
+
* fields. What it adds is the refusal that issue #211 asked for. The `value`
|
|
1329
|
+
* slot is a PHP `preg_*` PATTERN, so a `c.text("^XanoTS.*Engine$")` there is not
|
|
1330
|
+
* a stricter assertion — it is a pattern the engine cannot run, and the test
|
|
1331
|
+
* fails against the very string it was written for:
|
|
1332
|
+
*
|
|
1333
|
+
* ```
|
|
1334
|
+
* to_match failed - regex /"^XanoTS.*Engine$"/ not matched in "XanoTS Automated Testing Engine"
|
|
1335
|
+
* ```
|
|
1336
|
+
*
|
|
1337
|
+
* The refusal is build-time and inspects the value it was handed, exactly as the
|
|
1338
|
+
* `fl.regex_*` guard does (#128): a bare `const` is refused and pointed at
|
|
1339
|
+
* `c.regex`, while a `ref`/`inp`/`env` pattern — whose text is not visible here —
|
|
1340
|
+
* is passed through untouched.
|
|
1341
|
+
*/
|
|
1342
|
+
declare function expectToMatch(a?: ExpectToMatchArgs): Statement;
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Hand-authored typed wrapper for `util.ip_lookup` (#226) — the geolocation
|
|
1346
|
+
* statement whose bound variable is a NESTED object that nothing in the
|
|
1347
|
+
* signature hints at.
|
|
1348
|
+
*
|
|
1349
|
+
* The generated factory types `value` and nothing else, so an author guessing a
|
|
1350
|
+
* flat `{ city, region, latitude, longitude }` gets `null` for every field, and
|
|
1351
|
+
* those nulls fail two steps later with errors that name a column rather than
|
|
1352
|
+
* the lookup. This wrapper delegates encoding to the generated factory (bytes
|
|
1353
|
+
* unchanged) and adds the shape brand, so `ref("geo.location.latitude")` traces
|
|
1354
|
+
* to `number | null` while `ref("geo.latitude")` bottoms out at `unknown`.
|
|
1355
|
+
*/
|
|
1356
|
+
|
|
1357
|
+
/**
|
|
1358
|
+
* What `util.ip_lookup` binds to its `as` variable: a nested geolocation record,
|
|
1359
|
+
* **not** flat fields. Every leaf is nullable, and `region.*`/`city.name`/
|
|
1360
|
+
* `postal.code` are commonly null even for a well-known routable public address
|
|
1361
|
+
* — a populated `country`/`location` with an empty city is the normal result,
|
|
1362
|
+
* not a failed lookup.
|
|
1363
|
+
*
|
|
1364
|
+
* Read coordinates at `location.latitude`/`location.longitude` and place names
|
|
1365
|
+
* at `city.name`/`region.name`/`country.name`. Note that `city` itself is an
|
|
1366
|
+
* OBJECT: a `ref("geo.city")` written into a text column fails on the object,
|
|
1367
|
+
* and `{ safe: true }` does not help because the object is not null — drill to
|
|
1368
|
+
* `city.name` and supply a fallback.
|
|
1369
|
+
*
|
|
1370
|
+
* The whole variable is `null` when the address cannot be resolved at all
|
|
1371
|
+
* (a private/reserved range, an unroutable or malformed address), so guard the
|
|
1372
|
+
* top level before drilling.
|
|
1373
|
+
*/
|
|
1374
|
+
interface IpLookupResult {
|
|
1375
|
+
/** Continent code (`"NA"`) and name (`"North America"`). */
|
|
1376
|
+
continent: {
|
|
1377
|
+
code: string | null;
|
|
1378
|
+
name: string | null;
|
|
1379
|
+
};
|
|
1380
|
+
/** ISO-3166 alpha-2 country code (`"US"`) and name (`"United States"`). */
|
|
1381
|
+
country: {
|
|
1382
|
+
code: string | null;
|
|
1383
|
+
name: string | null;
|
|
1384
|
+
};
|
|
1385
|
+
/** Most specific subdivision — state/province. Commonly null. */
|
|
1386
|
+
region: {
|
|
1387
|
+
code: string | null;
|
|
1388
|
+
name: string | null;
|
|
1389
|
+
};
|
|
1390
|
+
/** City name only; there is no city code. Commonly null. */
|
|
1391
|
+
city: {
|
|
1392
|
+
name: string | null;
|
|
1393
|
+
};
|
|
1394
|
+
/** Postal/ZIP code. Commonly null. */
|
|
1395
|
+
postal: {
|
|
1396
|
+
code: string | null;
|
|
1397
|
+
};
|
|
1398
|
+
/** Coordinates, IANA timezone (`"America/Chicago"`), and accuracy radius in KILOMETRES. */
|
|
1399
|
+
location: {
|
|
1400
|
+
latitude: number | null;
|
|
1401
|
+
longitude: number | null;
|
|
1402
|
+
tz: string | null;
|
|
1403
|
+
radius: number | null;
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
interface IpLookupArgs<As extends string = string> extends StatementOptions {
|
|
1407
|
+
/** The IP address to geolocate. */
|
|
1408
|
+
value: Value;
|
|
1409
|
+
/** Bind the nested {@link IpLookupResult} (or `null`) to this stack variable. */
|
|
1410
|
+
as?: As;
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* `s.util.ip_lookup({ value, as })` — geolocate an IP address
|
|
1414
|
+
* (`mvp:ipaddress_lookup`).
|
|
1415
|
+
*
|
|
1416
|
+
* Branded `AsShapeBrand<As, IpLookupResult | null>` so `InferResponse` resolves
|
|
1417
|
+
* a dotted `ref` into the real, nested shape instead of `unknown`. The brand is
|
|
1418
|
+
* phantom — the emitted statement is byte-identical to the generated factory's.
|
|
1419
|
+
*/
|
|
1420
|
+
declare function ipLookup<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a: IpLookupArgs<As> & {
|
|
1421
|
+
asFilters?: Fs;
|
|
1422
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<IpLookupResult | null, Fs>>;
|
|
1423
|
+
|
|
1424
|
+
/**
|
|
1425
|
+
* Addon-authoring encoder — the one place that turns an authored {@link AddonSpec}
|
|
1426
|
+
* into the stored `addon[]` block a db statement carries (the shape the engine's
|
|
1427
|
+
* addon import/export walk reads).
|
|
1428
|
+
*
|
|
1429
|
+
* Xano addons graft related-table data onto the rows a `db.query`/`db.get` (and
|
|
1430
|
+
* the other row-returning db ops) return. Each attached addon references a
|
|
1431
|
+
* reusable addon object, maps some of its inputs, optionally restricts its
|
|
1432
|
+
* output columns, and lands its result on the row under a dotted destination
|
|
1433
|
+
* (`offset` + `as`). Addons nest recursively.
|
|
1434
|
+
*
|
|
1435
|
+
* The authoring surface mirrors XanoScript's `addon = [{ name, as, input, output,
|
|
1436
|
+
* addon }]`, with two deliberate divergences:
|
|
1437
|
+
*
|
|
1438
|
+
* - the reference field is named `addon` (an {@link ObjectRef}), so the nesting
|
|
1439
|
+
* field is named `children` to avoid the collision — which also matches the
|
|
1440
|
+
* stored/export key (KTD-3);
|
|
1441
|
+
* - the target is a guid-native `ObjectRef`, resolved to a guid and emitted under
|
|
1442
|
+
* the stored `id` key. In a packageExport bundle the engine matches addons by
|
|
1443
|
+
* guid (`importAddonId` → `guidMatch`), so emitting the guid as `id` is correct
|
|
1444
|
+
* — the same precedent `s.addon.call` uses (KTD-1).
|
|
1445
|
+
*/
|
|
1446
|
+
|
|
1447
|
+
/**
|
|
1448
|
+
* One addon attached to a db statement.
|
|
1449
|
+
*
|
|
1450
|
+
* `as` is the dotted destination on the row (e.g. `"items._book"`); it splits at
|
|
1451
|
+
* the last dot into the stored `offset` (path prefix) + `as` (final segment).
|
|
1452
|
+
* `input` maps addon input names to values — bind parent-row columns with
|
|
1453
|
+
* {@link out} (`{ user_id: out("id") }`). `output` restricts the addon's returned
|
|
1454
|
+
* columns. `children` nests further addons (recursive).
|
|
1455
|
+
*/
|
|
1456
|
+
interface AddonSpec<Graft = unknown> {
|
|
1457
|
+
/**
|
|
1458
|
+
* The target addon. A typed {@link AddonDef} handle (from {@link addon}) carries
|
|
1459
|
+
* its graft shape into the parent row's response type; a bare name/`ObjectRef`
|
|
1460
|
+
* resolves to a guid but grafts `unknown`.
|
|
1461
|
+
*
|
|
1462
|
+
* `null` is the UNBOUND attachment the engine stores as `id: ""` — an addon
|
|
1463
|
+
* that was deleted or never bound. It exists so `codegen` can reproduce such a
|
|
1464
|
+
* query faithfully instead of throwing and degrading the whole statement to
|
|
1465
|
+
* `raw()`; it grafts `unknown`, which is what an unbound target knows.
|
|
1466
|
+
*/
|
|
1467
|
+
addon: ObjectRef | AddonDef<Graft> | null;
|
|
1468
|
+
/**
|
|
1469
|
+
* Dotted destination **relative to a returned row**, e.g. `"_book"` (a bare
|
|
1470
|
+
* alias) or `"obj._book"` (offset + alias). Splits at the last dot into the
|
|
1471
|
+
* stored `offset` (path prefix) + `as` (final segment). Do **not** hand-write
|
|
1472
|
+
* the `items[]` paging-envelope prefix — a `db.query` that returns a metadata
|
|
1473
|
+
* paging envelope adds it automatically (writing it explicitly is tolerated and
|
|
1474
|
+
* not double-prefixed).
|
|
1475
|
+
*/
|
|
1476
|
+
as: string;
|
|
1477
|
+
/** Addon input bindings, name → value (use {@link out} for parent-row columns). */
|
|
1478
|
+
input?: Record<string, Value>;
|
|
1479
|
+
/** Restrict the addon's returned columns. Narrows the graft at runtime and in
|
|
1480
|
+
* the grafted type (to `output ∩ the addon's columns`). A dotted entry
|
|
1481
|
+
* (`"img.url"`) selects sub-keys of an object column; the graft narrows by the
|
|
1482
|
+
* root segment, since an object column's sub-keys are not declared. */
|
|
1483
|
+
output?: readonly string[];
|
|
1484
|
+
/** Nested addons (recursive). */
|
|
1485
|
+
children?: AddonSpec[];
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
/**
|
|
1489
|
+
* Hand-authored database statements (U10) — the `!map:dbo` family: read/delete/
|
|
1490
|
+
* exists/patch/truncate/schema against a table. Codegen defers these because the
|
|
1491
|
+
* target table is a `!map:dbo context.dbo.id` reference; with the guid
|
|
1492
|
+
* foundation (refs/guid.ts) the table resolves to its deterministic guid.
|
|
1493
|
+
*
|
|
1494
|
+
* All six share one rich envelope (engine-class metadata, not in the transform
|
|
1495
|
+
* schema — confirmed against the Xano engine's persisted shape): `description:""`,
|
|
1496
|
+
* `settings_registry:[]`, an `output` block (`{customize:false,filters:[],items:[]}`
|
|
1497
|
+
* by default; a statement with column selection — `db.get`'s `output` arg — emits
|
|
1498
|
+
* `{customize:true, items:[{name,children:[]}]}` per the engine's persisted golden),
|
|
1499
|
+
* `addon:[]`, an always-present `as` (""-default), and `context:{dbo:{id:guid}}`.
|
|
1500
|
+
* Input entries are the rich form `{name,value,tag,filters,ignore,expand,children}`.
|
|
1501
|
+
*
|
|
1502
|
+
* The row-data writes (`db.add`/`db.edit`/`db.add_or_edit`) carry the row as
|
|
1503
|
+
* explicit input entries — one per field, each with an optional `ignore` flag
|
|
1504
|
+
* (system/readonly columns like `id` are stored with `ignore:true`). Authors can
|
|
1505
|
+
* either list the entries exactly (`data: DbField[]`) or pass a *partial* row
|
|
1506
|
+
* (`row: { … }`) and let {@link expandRow} fill it against the table's declared
|
|
1507
|
+
* columns with type defaults + a documented `ignore` heuristic. The latter is a
|
|
1508
|
+
* DX convenience, not a byte-clone of the engine's editor template (see
|
|
1509
|
+
* {@link expandRow} for why that template isn't reproducible — it's a frontend
|
|
1510
|
+
* artifact, and the engine's import path accepts whatever entries it's given).
|
|
1511
|
+
*
|
|
1512
|
+
* Scope: `db.add_or_edit` (extra `context.dbo.as` + inconsistent entries),
|
|
1513
|
+
* `db.bulk*` (array-of-rows), `db.query` (structural !function), and
|
|
1514
|
+
* `db.direct_query`/external SQL/`db.transaction` are deferred.
|
|
1515
|
+
*/
|
|
1516
|
+
|
|
1517
|
+
/**
|
|
1518
|
+
* The column-name type for a db op's `table` argument: a typed `table()` handle
|
|
1519
|
+
* narrows to its declared columns (+ system columns); a bare name or an untyped
|
|
1520
|
+
* ref falls back to any `string`. Drives schema-aware typing of `fieldName`,
|
|
1521
|
+
* `output`, `sortBy`, and `row` keys.
|
|
1522
|
+
*/
|
|
1523
|
+
type ColsOf<T> = T extends TableDef<infer C> ? C : string;
|
|
1524
|
+
/**
|
|
1525
|
+
* The aliases a query's own `eval` declares — computed columns that exist on the
|
|
1526
|
+
* result but on no table.
|
|
1527
|
+
*
|
|
1528
|
+
* `eval: [{name: "…$searchindex", as: "rank", filters: [{name: "search_rank"}]}]`
|
|
1529
|
+
* makes `rank` selectable and sortable in the SAME call, and the engine's docs
|
|
1530
|
+
* (and this SDK's) say so: each `as` grafts onto the row. Typed only against the
|
|
1531
|
+
* table's columns, `sortBy: "rank"` did not compile — six selections in one real
|
|
1532
|
+
* workspace, all of them valid.
|
|
1533
|
+
*/
|
|
1534
|
+
type EvalAliases<E> = E extends readonly (infer Item)[] ? Item extends {
|
|
1535
|
+
as: infer A extends string;
|
|
1536
|
+
} ? A : never : never;
|
|
1537
|
+
/**
|
|
1538
|
+
* The single-row shape a db read yields, for `InferResponse`'s trace (U5): the
|
|
1539
|
+
* table's {@link InferRow}, narrowed to the selected `Cols` when an `output`
|
|
1540
|
+
* list is given, else the full row. A bare-name / raw-`ColumnDef[]` table has no
|
|
1541
|
+
* field brands, so `InferRow` is `never` → `unknown` (nothing to infer).
|
|
1542
|
+
*/
|
|
1543
|
+
type RowShapeOf<T extends ObjectRef, Cols extends readonly string[]> = [
|
|
1544
|
+
InferRow<T>
|
|
1545
|
+
] extends [never] ? unknown : Cols["length"] extends 0 ? InferRow<T> : Pick<InferRow<T>, Extract<OutputRoot<Cols[number]>, keyof InferRow<T>>>;
|
|
1546
|
+
/**
|
|
1547
|
+
* The full-row shape a write binds when it carries no column selection —
|
|
1548
|
+
* `db.add_or_edit` (upserted row, which has no `output` envelope at all in its
|
|
1549
|
+
* leaner serialization) and the bulk ops. The whole {@link InferRow}, or
|
|
1550
|
+
* `unknown` for an unbranded bare-name table. Expressed via {@link RowShapeOf}
|
|
1551
|
+
* with an empty `Cols` so the `never`→`unknown` guard is shared with the reads.
|
|
1552
|
+
* (`db.del` is deliberately *not* here — it binds `null`; see {@link dbDel}.)
|
|
1553
|
+
*/
|
|
1554
|
+
type FullRowShapeOf<T extends ObjectRef> = RowShapeOf<T, readonly []>;
|
|
1555
|
+
/**
|
|
1556
|
+
* The alias segment of a dotted addon `as` — the part after the last dot
|
|
1557
|
+
* (`"items._book"` → `"_book"`, `"_book"` → `"_book"`). This is the key the addon
|
|
1558
|
+
* grafts onto the row.
|
|
1559
|
+
*/
|
|
1560
|
+
type AddonAlias<S extends string> = S extends `${string}.${infer Rest}` ? AddonAlias<Rest> : S;
|
|
1561
|
+
/** True only for `unknown` (not `any`, not a concrete type) — guards the graft narrowing below. */
|
|
1562
|
+
type IsUnknown<T> = 0 extends 1 & T ? false : unknown extends T ? true : false;
|
|
1563
|
+
/**
|
|
1564
|
+
* Narrow a graft `G` to the attachment's `output` column whitelist `O`. The
|
|
1565
|
+
* runtime intersects the def's selected columns with the attachment whitelist
|
|
1566
|
+
* (`whitelistOutput`), so the type picks `O ∩ keyof G`. Applied to the element
|
|
1567
|
+
* of a list graft (`Shape[]`) or a single graft (`Shape`). An `unknown` graft
|
|
1568
|
+
* (bare-name reference, or a def with no typed `output`) stays `unknown` — never
|
|
1569
|
+
* collapse it to `{}`.
|
|
1570
|
+
*/
|
|
1571
|
+
type NarrowGraft<G, O extends readonly string[]> = IsUnknown<G> extends true ? unknown : G extends readonly (infer E)[] ? Prettify<Pick<E, Extract<OutputRoot<O[number]>, keyof E>>>[] : G extends object ? Prettify<Pick<G, Extract<OutputRoot<O[number]>, keyof G>>> : G;
|
|
1572
|
+
/**
|
|
1573
|
+
* The graft shape one attached addon lands on the row. A typed
|
|
1574
|
+
* {@link AddonDef} handle carries its shape (`Pick<row, output>`, an object or
|
|
1575
|
+
* array per its cardinality); a bare name/`ObjectRef` reference carries none, so
|
|
1576
|
+
* it grafts `unknown` — the honest floor (narrow it at the call site). An
|
|
1577
|
+
* attachment-level `output` further restricts the graft to those columns
|
|
1578
|
+
* ({@link NarrowGraft}).
|
|
1579
|
+
*/
|
|
1580
|
+
type GraftOf<H> = H extends {
|
|
1581
|
+
addon: AddonDef<infer G>;
|
|
1582
|
+
} ? H extends {
|
|
1583
|
+
output: infer O extends readonly string[];
|
|
1584
|
+
} ? NarrowGraft<G, O> : G : unknown;
|
|
1585
|
+
/**
|
|
1586
|
+
* The keys a set of attached addons graft onto each returned row. Each addon's
|
|
1587
|
+
* alias (the last segment of its `as`) becomes a key valued by {@link GraftOf}.
|
|
1588
|
+
*
|
|
1589
|
+
* Mirrors the engine's `applyAddOnSchema` placement — the alias always lands on
|
|
1590
|
+
* the *row element*. With paging the engine wraps rows under `items` (returnAs),
|
|
1591
|
+
* so `as:"items._book"` puts `_book` inside each `items[]` element = each row;
|
|
1592
|
+
* without paging `as:"_book"` puts it on each bare row. Both reduce to "the row
|
|
1593
|
+
* gains the alias key". Nested `children` addons enrich the addon's own result
|
|
1594
|
+
* (under the alias), so they add no parent-visible keys.
|
|
1595
|
+
*/
|
|
1596
|
+
type AddonFields<A> = A extends readonly [infer H, ...infer Rest] ? (H extends {
|
|
1597
|
+
as: infer S extends string;
|
|
1598
|
+
} ? {
|
|
1599
|
+
[K in AddonAlias<S>]: GraftOf<H>;
|
|
1600
|
+
} : object) & AddonFields<Rest> : object;
|
|
1601
|
+
/**
|
|
1602
|
+
* A row shape augmented with any addon-grafted alias keys. With no addons
|
|
1603
|
+
* (`A = readonly []`) it is the row unchanged, so the non-addon path — and every
|
|
1604
|
+
* existing caller — keeps its exact shape.
|
|
1605
|
+
*
|
|
1606
|
+
* The graft **overrides** any base column of the same name rather than
|
|
1607
|
+
* intersecting with it (`Omit<Row, alias> & AddonFields`): the engine overwrites
|
|
1608
|
+
* the field with the addon result at runtime, so when an alias shadows an
|
|
1609
|
+
* existing column the honest type is the graft (`unknown`), not the base column.
|
|
1610
|
+
* An intersection would collapse `unknown & string` back to the base column and
|
|
1611
|
+
* silently desync the type from runtime (issue #61).
|
|
1612
|
+
*/
|
|
1613
|
+
type WithAddons<Row, A> = [keyof AddonFields<A>] extends [never] ? Row : Prettify<Omit<Row, keyof AddonFields<A>> & AddonFields<A>>;
|
|
1614
|
+
/**
|
|
1615
|
+
* A row shape augmented with any `eval` alias keys. With no evals it is the row
|
|
1616
|
+
* unchanged. Like {@link WithAddons}, an eval alias **overrides** a base column of
|
|
1617
|
+
* the same name (the engine computes over it), so the honest type is the graft.
|
|
1618
|
+
*/
|
|
1619
|
+
type WithEval<Row, E> = [keyof EvalFields<E>] extends [never] ? Row : Prettify<Omit<Row, keyof EvalFields<E>> & EvalFields<E>>;
|
|
1620
|
+
/**
|
|
1621
|
+
* The paging metadata envelope a `db.query` returns when `paging` is set with
|
|
1622
|
+
* metadata on — the engine's `packageListMeta` shape (issue #58). The result
|
|
1623
|
+
* list lives under `items`; `totals:true` adds `itemsTotal`/`pageTotal`. A query
|
|
1624
|
+
* with no `paging`, or `paging:{ metadata:false }`, returns the bare list instead.
|
|
1625
|
+
*
|
|
1626
|
+
* **Has-next signal (issue #66 bonus):** read `nextPage` — it is `number` when
|
|
1627
|
+
* another page exists and `null` on the last page (the engine fetches one extra
|
|
1628
|
+
* row to decide, so this needs no second scan). For a total count, set
|
|
1629
|
+
* `paging:{ totals:true }` and read `itemsTotal`/`pageTotal`. Both are typed on
|
|
1630
|
+
* this envelope by `InferResponse`, so a client can drive "load more" straight
|
|
1631
|
+
* off the typed response without hand-declaring the shape.
|
|
1632
|
+
*/
|
|
1633
|
+
type PagingEnvelope<Items, Totals extends boolean> = Prettify<{
|
|
1634
|
+
items: Items;
|
|
1635
|
+
itemsReceived: number;
|
|
1636
|
+
curPage: number;
|
|
1637
|
+
nextPage: number | null;
|
|
1638
|
+
prevPage: number | null;
|
|
1639
|
+
offset: number;
|
|
1640
|
+
perPage: number;
|
|
1641
|
+
} & (Totals extends true ? {
|
|
1642
|
+
itemsTotal: number;
|
|
1643
|
+
pageTotal: number;
|
|
1644
|
+
} : object)>;
|
|
1645
|
+
/**
|
|
1646
|
+
* Whether a `paging` arg carries a page/per_page/offset field (static or a
|
|
1647
|
+
* `Value`) — the runtime gate that activates pagination. A `search`/`sort`-only
|
|
1648
|
+
* `paging` has no such field, so it does not produce the envelope.
|
|
1649
|
+
*/
|
|
1650
|
+
type HasPageFieldT<P> = P extends {
|
|
1651
|
+
page: unknown;
|
|
1652
|
+
} ? true : P extends {
|
|
1653
|
+
per_page: unknown;
|
|
1654
|
+
} ? true : P extends {
|
|
1655
|
+
offset: unknown;
|
|
1656
|
+
} ? true : false;
|
|
1657
|
+
/**
|
|
1658
|
+
* Whether a `paging` arg produces the metadata envelope: it activates pagination
|
|
1659
|
+
* (a page/per_page/offset field is present) and is not explicitly `metadata:false`
|
|
1660
|
+
* (the engine default is `metadata:true`).
|
|
1661
|
+
*/
|
|
1662
|
+
type HasPagingEnvelope<P> = P extends undefined ? false : P extends {
|
|
1663
|
+
metadata: false;
|
|
1664
|
+
} ? false : HasPageFieldT<P> extends true ? true : false;
|
|
1665
|
+
/** The `totals` flag of a `paging` arg — literal `true` only when set explicitly. */
|
|
1666
|
+
type PagingTotals<P> = P extends {
|
|
1667
|
+
totals: true;
|
|
1668
|
+
} ? true : false;
|
|
1669
|
+
/**
|
|
1670
|
+
* The engine's `context.return.type` for a `db.query` — the return-type
|
|
1671
|
+
* discriminant. `"list"` is the default (a row array or paging envelope);
|
|
1672
|
+
* `"single"` a first-match object; `"count"`/`"exists"` a scalar; `"stream"` a
|
|
1673
|
+
* (pageable) row array with no metadata envelope.
|
|
1674
|
+
*/
|
|
1675
|
+
type DbReturnType = "list" | "single" | "count" | "exists" | "stream" | "aggregate";
|
|
1676
|
+
/** Distinct-row handling (`context.return.<list|stream>.distinct`): engine default `"auto"`. */
|
|
1677
|
+
type DbDistinct = "auto" | "yes" | "no";
|
|
1678
|
+
/** Aggregate paging (`context.return.aggregate.paging`) — no `offset`/`totals` (engine schema). */
|
|
1679
|
+
interface DbAggregatePaging {
|
|
1680
|
+
page?: number;
|
|
1681
|
+
per_page?: number;
|
|
1682
|
+
/** Wrap the result in the metadata envelope (engine default `true`). */
|
|
1683
|
+
metadata?: boolean;
|
|
1684
|
+
/**
|
|
1685
|
+
* The engine's gate. Every field here is read ONLY when this is on, so
|
|
1686
|
+
* `enabled:false` parks a configured block without applying it — the state the
|
|
1687
|
+
* editor leaves behind when pagination is switched back off. Defaults to `true`
|
|
1688
|
+
* (passing `paging` at all is the usual way to ask for it); set `false` only to
|
|
1689
|
+
* reproduce that parked state.
|
|
1690
|
+
*/
|
|
1691
|
+
enabled?: boolean;
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Aggregate/group-by config for `returnType:"aggregate"` (`context.return.aggregate`).
|
|
1695
|
+
* `group` are the group-by columns and `eval` the aggregator columns (each
|
|
1696
|
+
* `{ name, as, filters }` — an aggregator like `sum`/`count` rides `filters`).
|
|
1697
|
+
* Both `as` sets graft onto the aggregate row (`unknown` values). Write `name` as
|
|
1698
|
+
* a bare column (`"status"`) — it is alias-qualified to `"<table>.status"` on emit
|
|
1699
|
+
* (the engine requires the qualified form) and the statement declares that alias
|
|
1700
|
+
* so the qualified name resolves; pass an already-dotted `name` for a
|
|
1701
|
+
* `bind`ed/joined column and it is left as-is (and declares nothing, which is
|
|
1702
|
+
* what keeps a pulled workspace byte-exact — see issue #213).
|
|
1703
|
+
*/
|
|
1704
|
+
interface DbAggregate {
|
|
1705
|
+
group?: DbEval[];
|
|
1706
|
+
eval?: DbEval[];
|
|
1707
|
+
sort?: SortDirective[];
|
|
1708
|
+
paging?: DbAggregatePaging;
|
|
1709
|
+
}
|
|
1710
|
+
/** A join type for a {@link DbBind} — the engine's `bind[].join`. */
|
|
1711
|
+
type DbJoin = "inner" | "left" | "right";
|
|
1712
|
+
/**
|
|
1713
|
+
* A db statement's target table — a def handle or name, or `null` for the
|
|
1714
|
+
* engine's own empty binding (`context.dbo.id: ""`).
|
|
1715
|
+
*
|
|
1716
|
+
* ⚠ **Do not author `null`.** It is a BROKEN state in Xano, not a neutral one:
|
|
1717
|
+
* the statement is bound to no table and does nothing wherever it runs. It exists
|
|
1718
|
+
* on these types so `codegen` can represent a broken statement faithfully rather
|
|
1719
|
+
* than degrade the whole thing to `raw()` — a pulled `table: null` is a defect to
|
|
1720
|
+
* fix in the pulled workspace, not a shape to copy.
|
|
1721
|
+
*
|
|
1722
|
+
* It is what a statement degrades to when the table it referenced is deleted, and
|
|
1723
|
+
* also where a freshly-dropped one starts. The engine clears the id rather than
|
|
1724
|
+
* recording a tombstone, so those two are the same bytes: `null` means "unbound",
|
|
1725
|
+
* never "was deleted". The same contract as an addon's `table` (see
|
|
1726
|
+
* {@link addon}), which is where this pattern comes from.
|
|
1727
|
+
*
|
|
1728
|
+
* An unbound table has no schema, so `row:` (which expands the typed row against
|
|
1729
|
+
* the table's columns) is unavailable with it — use `data:`.
|
|
1730
|
+
*/
|
|
1731
|
+
type DbTableRef<T extends ObjectRef = ObjectRef> = T | null;
|
|
1732
|
+
/**
|
|
1733
|
+
* A join (`context.bind[]`): join `table` (aliased by `as`) with `join` kind and
|
|
1734
|
+
* an optional `where` join condition (same search surface as the query). Joins
|
|
1735
|
+
* widen what `where`/`sort`/`eval` can address by dotted path (`"author.id"`);
|
|
1736
|
+
* they do not by themselves change the returned row shape.
|
|
1737
|
+
*
|
|
1738
|
+
* ⚠ **The two sides of a join condition are spelled differently** (issue #213).
|
|
1739
|
+
* The JOINED column takes the dotted alias path; the query's OWN column stays
|
|
1740
|
+
* BARE:
|
|
1741
|
+
*
|
|
1742
|
+
* ```ts
|
|
1743
|
+
* s.db.query({
|
|
1744
|
+
* table: doc, // columns of `doc` are bare
|
|
1745
|
+
* bind: [{ table: team, as: "team_row", join: "left",
|
|
1746
|
+
* where: expr(col("team"), "=", col("team_row.id")) }],
|
|
1747
|
+
* })
|
|
1748
|
+
* ```
|
|
1749
|
+
*
|
|
1750
|
+
* Qualifying your own column with the table's name (`col("doc.team")`) resolves
|
|
1751
|
+
* only when the query also sets {@link DbQueryArgs.tableAlias} — the engine
|
|
1752
|
+
* matches the qualifier against the alias the statement declares, and a query
|
|
1753
|
+
* without `tableAlias` declares none. Unqualified, the engine treats the operand
|
|
1754
|
+
* as a text literal and the request fails with `ParseError: Invalid value for
|
|
1755
|
+
* param:"…"` naming the OTHER operand. Both spellings are checked at export.
|
|
1756
|
+
*/
|
|
1757
|
+
interface DbBind {
|
|
1758
|
+
/**
|
|
1759
|
+
* The table to join, or `null` when unbound — see {@link DbTableRef} for the
|
|
1760
|
+
* contract, which is the same one the query's own `table` holds. ⚠ Do not
|
|
1761
|
+
* author `null`; it exists so a join whose table was deleted round-trips
|
|
1762
|
+
* instead of taking the whole statement to `raw()`.
|
|
1763
|
+
*/
|
|
1764
|
+
table: DbTableRef;
|
|
1765
|
+
/** SQL alias for the joined table — defaults to the table name. Two binds to the same table need distinct aliases. */
|
|
1766
|
+
as?: string;
|
|
1767
|
+
/** Join kind (default `"inner"`). */
|
|
1768
|
+
join?: DbJoin;
|
|
1769
|
+
/** Join condition — same `where`/`cmp`/`and`/`or` surface as the query. */
|
|
1770
|
+
where?: DbWhere;
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* The full `db.query` result shape, discriminated by return type `RT`:
|
|
1774
|
+
* `count → number`, `exists → boolean`, `single → row | null`, `stream → row[]`,
|
|
1775
|
+
* and `list → row[]` or the {@link PagingEnvelope} when `paging` requests
|
|
1776
|
+
* metadata. The row is always the addon-augmented row.
|
|
1777
|
+
*/
|
|
1778
|
+
type QueryResult<Row, A, P, RT extends DbReturnType, E = readonly [], AG = unknown> = RT extends "count" ? number : RT extends "exists" ? boolean : RT extends "aggregate" ? AggregateRow<AG>[] : WithAddons<WithEval<Row, E>, A> extends infer R ? RT extends "single" ? R | null : RT extends "stream" ? R[] : HasPagingEnvelope<P> extends true ? PagingEnvelope<R[], PagingTotals<P>> : R[] : never;
|
|
1779
|
+
/**
|
|
1780
|
+
* A db read statement branded — **at the type level only** — via the shared
|
|
1781
|
+
* {@link AsShapeBrand} contract (the stack variable it binds + the shape it
|
|
1782
|
+
* produces). The runtime statement is a plain {@link Statement}, so
|
|
1783
|
+
* `encodeStatement` is unchanged.
|
|
1784
|
+
*/
|
|
1785
|
+
type DbResult<As extends string, Shape> = Statement & AsShapeBrand<As, Shape>;
|
|
1786
|
+
interface DbGetArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
|
|
1787
|
+
/**
|
|
1788
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
1789
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
1790
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
1791
|
+
*/
|
|
1792
|
+
tableAlias?: string;
|
|
1793
|
+
/** The target table (def handle or name). */
|
|
1794
|
+
table: DbTableRef<T>;
|
|
1795
|
+
/**
|
|
1796
|
+
* The lookup field (defaults to the primary key `id`). A dotted path reaches a
|
|
1797
|
+
* sub-key of an object column (`"google_oauth.id"`) or a joined table's column
|
|
1798
|
+
* — see {@link QualifiedCol}.
|
|
1799
|
+
*/
|
|
1800
|
+
fieldName?: QualifiedCol<ColsOf<T>>;
|
|
1801
|
+
/** The value to match. */
|
|
1802
|
+
fieldValue: Value;
|
|
1803
|
+
/** Acquire a row lock for the transaction. */
|
|
1804
|
+
lock?: boolean;
|
|
1805
|
+
/**
|
|
1806
|
+
* Restrict the returned columns (XanoScript `output = [...]`). Encoded into
|
|
1807
|
+
* the customized output envelope — `{customize:true, items:[{name,children:[]}]}`
|
|
1808
|
+
* (byte shape per the engine's persisted golden). Omitting it
|
|
1809
|
+
* returns the full record (`customize:false`). Note: an explicit `output`
|
|
1810
|
+
* list overrides column visibility — listing an `internal` column (e.g. a
|
|
1811
|
+
* password hash) pulls it into the statement result. Captured literally so
|
|
1812
|
+
* `InferResponse` narrows a traced row to exactly these columns.
|
|
1813
|
+
*/
|
|
1814
|
+
output?: Cols;
|
|
1815
|
+
/** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
|
|
1816
|
+
* addon's alias (the last segment of its `as`) is merged onto the row shape in
|
|
1817
|
+
* `InferResponse` — typed from the addon's graft shape when it's a typed
|
|
1818
|
+
* `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
|
|
1819
|
+
addon?: A;
|
|
1820
|
+
/** Capture the row into this stack variable. Captured literally so
|
|
1821
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
1822
|
+
as?: As;
|
|
1823
|
+
}
|
|
1824
|
+
/** `db.get <table>` — fetch a single record by a field match (`mvp:dbo_getby`).
|
|
1825
|
+
* Returns a {@link DbResult} branded with `as` + the (optionally narrowed) row
|
|
1826
|
+
* shape **`| null`** so `InferResponse` can type a response that returns this
|
|
1827
|
+
* variable. `dbo_getby` binds **`null` on a miss** (no row matched) rather than
|
|
1828
|
+
* throwing — confirmed live — so the honest shape is `Row | null`, matching
|
|
1829
|
+
* `db.query`'s `returnType:"single"` ({@link QueryResult}). Contrast the row
|
|
1830
|
+
* **writes** (`db.add`/`edit`/`patch`/`add_or_edit`), which bind the full
|
|
1831
|
+
* written row rather than null and so stay non-nullable — a genuine miss throws
|
|
1832
|
+
* instead of yielding null (`NotFound`/404 for `edit`/`patch`; a
|
|
1833
|
+
* unique-constraint error for `add`; `add_or_edit` upserts, so it never misses)
|
|
1834
|
+
* (issue #105). */
|
|
1835
|
+
declare function dbGet<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbGetArgs<T, As, Cols, A> & {
|
|
1836
|
+
asFilters?: Fs;
|
|
1837
|
+
}): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A> | null, Fs>>;
|
|
1838
|
+
interface DbGetByIdArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
|
|
1839
|
+
/**
|
|
1840
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
1841
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
1842
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
1843
|
+
*/
|
|
1844
|
+
tableAlias?: string;
|
|
1845
|
+
/** The target table (def handle or name). */
|
|
1846
|
+
table: DbTableRef<T>;
|
|
1847
|
+
/** The primary key to fetch. The engine types this `int|min(1)`. */
|
|
1848
|
+
id: Value;
|
|
1849
|
+
/** Restrict the returned columns — same envelope as {@link DbGetArgs.output}. */
|
|
1850
|
+
output?: Cols;
|
|
1851
|
+
/** Attach addons to enrich the returned row (see {@link AddonSpec}). */
|
|
1852
|
+
addon?: A;
|
|
1853
|
+
/** Capture the row into this stack variable. */
|
|
1854
|
+
as?: As;
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* `db.get_by_id <table>` — fetch a single record by primary key (`mvp:dbo_get`).
|
|
1858
|
+
*
|
|
1859
|
+
* The narrow sibling of {@link dbGet}: where `db.get` matches any field
|
|
1860
|
+
* (`mvp:dbo_getby`, defaulting to `id`), this one is the engine's dedicated
|
|
1861
|
+
* get-by-primary-key statement and takes a single `id` input. Both are live in
|
|
1862
|
+
* real workspaces — which one the editor wrote is a matter of vintage and which
|
|
1863
|
+
* panel was used — so the SDK models both rather than rewriting one into the
|
|
1864
|
+
* other, which would change the stored bytes.
|
|
1865
|
+
*
|
|
1866
|
+
* Binds `Row | null` for the same reason `db.get` does: a miss yields null
|
|
1867
|
+
* rather than throwing.
|
|
1868
|
+
*/
|
|
1869
|
+
declare function dbGetById<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbGetByIdArgs<T, As, Cols, A> & {
|
|
1870
|
+
asFilters?: Fs;
|
|
1871
|
+
}): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A> | null, Fs>>;
|
|
1872
|
+
interface DbDelArgs<T extends ObjectRef = ObjectRef> extends StatementOptions {
|
|
1873
|
+
/**
|
|
1874
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
1875
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
1876
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
1877
|
+
*/
|
|
1878
|
+
tableAlias?: string;
|
|
1879
|
+
table: DbTableRef<T>;
|
|
1880
|
+
/** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
|
|
1881
|
+
fieldName?: QualifiedCol<ColsOf<T>>;
|
|
1882
|
+
fieldValue: Value;
|
|
1883
|
+
as?: string;
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* `db.del <table>` — delete a single record by a field match (`mvp:dbo_delby`);
|
|
1887
|
+
* throws `NotFound`/404 when nothing matches.
|
|
1888
|
+
*
|
|
1889
|
+
* Left **unbranded** (plain {@link Statement}), unlike the other single-record
|
|
1890
|
+
* writes: the engine declares no output schema for this statement and returns
|
|
1891
|
+
* nothing once the row is gone, so the bound `as` variable holds **`null`**, not
|
|
1892
|
+
* the deleted row. `InferResponse` therefore resolves a returned del var to
|
|
1893
|
+
* `unknown` — matching where the engine's own OpenAPI walk falls back to `json`.
|
|
1894
|
+
* (Contrast `db.add`/`edit`/`patch`/`add_or_edit`, which each return the written
|
|
1895
|
+
* row and so bind the full record.)
|
|
1896
|
+
*/
|
|
1897
|
+
declare function dbDel<T extends ObjectRef>(args: DbDelArgs<T>): Statement;
|
|
1898
|
+
interface DbHasArgs<T extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
|
|
1899
|
+
/**
|
|
1900
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
1901
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
1902
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
1903
|
+
*/
|
|
1904
|
+
tableAlias?: string;
|
|
1905
|
+
table: DbTableRef<T>;
|
|
1906
|
+
/** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
|
|
1907
|
+
fieldName?: QualifiedCol<ColsOf<T>>;
|
|
1908
|
+
fieldValue: Value;
|
|
1909
|
+
/** Capture the existence boolean into this stack variable. Captured literally so
|
|
1910
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
1911
|
+
as?: As;
|
|
1912
|
+
}
|
|
1913
|
+
/** `db.has <table>` — test whether a record exists by a field match (`mvp:dbo_hasby`).
|
|
1914
|
+
* Binds a **boolean** (the engine's `__self: bool` output), so it's branded with
|
|
1915
|
+
* `as` + `boolean` for `InferResponse` — table-independent, unlike the row ops. */
|
|
1916
|
+
declare function dbHas<T extends ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbHasArgs<T, As> & {
|
|
1917
|
+
asFilters?: Fs;
|
|
1918
|
+
}): DbResult<As, ApplyFilters<boolean, Fs>>;
|
|
1919
|
+
interface DbPatchArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
|
|
1920
|
+
/**
|
|
1921
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
1922
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
1923
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
1924
|
+
*/
|
|
1925
|
+
tableAlias?: string;
|
|
1926
|
+
table: DbTableRef<T>;
|
|
1927
|
+
/** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
|
|
1928
|
+
fieldName?: QualifiedCol<ColsOf<T>>;
|
|
1929
|
+
fieldValue: Value;
|
|
1930
|
+
/** The partial row to merge (an object value). */
|
|
1931
|
+
data: Value;
|
|
1932
|
+
/**
|
|
1933
|
+
* Restrict the columns of the RETURNED row (XanoScript `output = [...]`) —
|
|
1934
|
+
* the confirmation response only; it does not change what is written. Same
|
|
1935
|
+
* customized envelope as {@link DbGetArgs.output}, and offered on exactly the
|
|
1936
|
+
* write ops whose result is a row rather than a scalar: the editor hides the
|
|
1937
|
+
* customize control when a statement's whole output is a single `bool`/`int`
|
|
1938
|
+
* scalar (`db.del`, `db.has`), which is why those take no `output`.
|
|
1939
|
+
*/
|
|
1940
|
+
output?: Cols;
|
|
1941
|
+
/** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
|
|
1942
|
+
* addon's alias (the last segment of its `as`) is merged onto the row shape in
|
|
1943
|
+
* `InferResponse` — typed from the addon's graft shape when it's a typed
|
|
1944
|
+
* `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
|
|
1945
|
+
addon?: A;
|
|
1946
|
+
/** Capture the post-patch row into this stack variable. Captured literally so
|
|
1947
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
1948
|
+
as?: As;
|
|
1949
|
+
}
|
|
1950
|
+
/** `db.patch <table>` — partial-update a record by a field match (`mvp:dbo_patch`).
|
|
1951
|
+
* Binds the **full post-patch row** (`$updatedInst`), so it's branded with `as` +
|
|
1952
|
+
* the row shape for `InferResponse` (throws `NotFound`/404 when nothing matches). */
|
|
1953
|
+
declare function dbPatch<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbPatchArgs<T, As, Cols, A> & {
|
|
1954
|
+
asFilters?: Fs;
|
|
1955
|
+
}): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A>, Fs>>;
|
|
1956
|
+
interface DbTruncateArgs extends StatementOptions {
|
|
1957
|
+
/**
|
|
1958
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
1959
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
1960
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
1961
|
+
*/
|
|
1962
|
+
tableAlias?: string;
|
|
1963
|
+
table: DbTableRef;
|
|
1964
|
+
/** Reset auto-increment counters. */
|
|
1965
|
+
reset?: boolean;
|
|
1966
|
+
as?: string;
|
|
1967
|
+
}
|
|
1968
|
+
/** `db.truncate <table>` — empty a table (`mvp:dbo_truncate`). */
|
|
1969
|
+
declare function dbTruncate(args: DbTruncateArgs): Statement;
|
|
1970
|
+
/** One field of a row write: a column name, its value, and whether to skip it. */
|
|
1971
|
+
interface DbField {
|
|
1972
|
+
name: string;
|
|
1973
|
+
value: Value;
|
|
1974
|
+
/** Store with `ignore:true` (system/readonly column not written), e.g. `id`. */
|
|
1975
|
+
ignore?: boolean;
|
|
1976
|
+
/**
|
|
1977
|
+
* Sub-entries for an object column: the engine builds the column's value from
|
|
1978
|
+
* these, keyed by each child's name, recursively (stored `expand:true`). The
|
|
1979
|
+
* entry's own `value` is still written — real workspaces carry either an empty
|
|
1980
|
+
* constant or a reference to the object the children were derived from — so it
|
|
1981
|
+
* stays authored rather than derived.
|
|
1982
|
+
*/
|
|
1983
|
+
children?: DbField[];
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* A row cell: any authored {@link Value} **except** a `col()` reference. A `col()`
|
|
1987
|
+
* (bare or wrapped in `withFilters`) does not resolve to the row's stored value
|
|
1988
|
+
* inside a `db.edit`/`db.add` `row` — it evaluates to `null` at runtime and a
|
|
1989
|
+
* following `fl.add(1)` aborts the engine (issue #32). The `__col?: never` bound
|
|
1990
|
+
* turns that live-only failure into a compile error; read the row first and pipe
|
|
1991
|
+
* `ref("...")` through the filter instead.
|
|
1992
|
+
*/
|
|
1993
|
+
type RowCell = Value & {
|
|
1994
|
+
readonly __col?: never;
|
|
1995
|
+
};
|
|
1996
|
+
/**
|
|
1997
|
+
* A nested cell: sub-keys written into an object column, keyed by name. Each
|
|
1998
|
+
* leaf is still a {@link RowCell}, so the `col()` guard above holds at every
|
|
1999
|
+
* depth — nesting adds a level, never an escape hatch.
|
|
2000
|
+
*
|
|
2001
|
+
* The column's own stored value is written as an empty constant, which is what
|
|
2002
|
+
* the overwhelming majority of real expanded entries carry. The one shape this
|
|
2003
|
+
* cannot express is an expanded column whose own value is a reference (the
|
|
2004
|
+
* editor seeds the children from it); author that through `data:` with explicit
|
|
2005
|
+
* `children`, which controls every byte.
|
|
2006
|
+
*/
|
|
2007
|
+
type NestedCell<C extends string = string> = {
|
|
2008
|
+
readonly [K in C]?: RowCell | NestedCell;
|
|
2009
|
+
};
|
|
2010
|
+
/** Recover a table handle's inferred row type, falling back to `unknown` for a bare name. */
|
|
2011
|
+
type RowsOf<T> = T extends TableDef<string, infer Row> ? Row : unknown;
|
|
2012
|
+
/**
|
|
2013
|
+
* A partial row keyed by column name — the values to write. Unspecified columns
|
|
2014
|
+
* get a type default on `db.add`; on `db.edit` they are marked `ignore:true` and
|
|
2015
|
+
* keep their stored value instead (issue #33 — see `expandRow`).
|
|
2016
|
+
*
|
|
2017
|
+
* A cell is a tagged {@link Value}, a {@link NestedCell}, or — since #75 — a bare
|
|
2018
|
+
* JS literal typed against that column ({@link ScalarCell}), which `expandRow`
|
|
2019
|
+
* coerces to the constant the author would otherwise have written by hand.
|
|
2020
|
+
*/
|
|
2021
|
+
type RowMap<C extends string = string, Row = unknown> = Partial<{
|
|
2022
|
+
[K in C]: RowCell | NestedCell | ScalarCell<K extends keyof Row ? Row[K] : unknown>;
|
|
2023
|
+
}>;
|
|
2024
|
+
interface DbAddArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
|
|
2025
|
+
/**
|
|
2026
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2027
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2028
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2029
|
+
*/
|
|
2030
|
+
tableAlias?: string;
|
|
2031
|
+
/**
|
|
2032
|
+
* Refuse to auto-wire request inputs the endpoint did not explicitly bind.
|
|
2033
|
+
*
|
|
2034
|
+
* A row write auto-wires any column whose name matches an incoming request
|
|
2035
|
+
* input, which is convenient and is also how a caller can reach a column the
|
|
2036
|
+
* endpoint never meant to expose. With this on, the engine consults the
|
|
2037
|
+
* endpoint's declared inputs and skips auto-wiring anything outside them;
|
|
2038
|
+
* explicit `data`/`row` entries are unaffected, because those are bindings you
|
|
2039
|
+
* wrote.
|
|
2040
|
+
*
|
|
2041
|
+
* Off by default, matching the engine's own default — so leaving it unset
|
|
2042
|
+
* writes nothing and changes nothing. Reach for it on any write whose table
|
|
2043
|
+
* has a column a caller must not set (`role`, `is_admin`, `credits`).
|
|
2044
|
+
*/
|
|
2045
|
+
enforceHiddenFields?: boolean;
|
|
2046
|
+
table: DbTableRef<T>;
|
|
2047
|
+
/** The row to insert as explicit entries (exact control over each field + `ignore`). */
|
|
2048
|
+
data?: DbField[];
|
|
2049
|
+
/** A partial row keyed by column name; expanded against the table's declared columns. */
|
|
2050
|
+
row?: RowMap<ColsOf<T>, RowsOf<T>>;
|
|
2051
|
+
/**
|
|
2052
|
+
* Restrict the columns of the RETURNED row (XanoScript `output = [...]`) —
|
|
2053
|
+
* the confirmation response only; it does not change what is written. Same
|
|
2054
|
+
* customized envelope as {@link DbGetArgs.output}, and offered on exactly the
|
|
2055
|
+
* write ops whose result is a row rather than a scalar: the editor hides the
|
|
2056
|
+
* customize control when a statement's whole output is a single `bool`/`int`
|
|
2057
|
+
* scalar (`db.del`, `db.has`), which is why those take no `output`.
|
|
2058
|
+
*/
|
|
2059
|
+
output?: Cols;
|
|
2060
|
+
/** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
|
|
2061
|
+
* addon's alias (the last segment of its `as`) is merged onto the row shape in
|
|
2062
|
+
* `InferResponse` — typed from the addon's graft shape when it's a typed
|
|
2063
|
+
* `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
|
|
2064
|
+
addon?: A;
|
|
2065
|
+
/** Capture the inserted row into this stack variable. Captured literally so
|
|
2066
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
2067
|
+
as?: As;
|
|
2068
|
+
}
|
|
2069
|
+
/** `db.add <table>` — insert a record (`mvp:dbo_add`). Binds the **full inserted
|
|
2070
|
+
* row** (including the auto-assigned `id`/`created_at`), so it's branded with
|
|
2071
|
+
* `as` + the row shape for `InferResponse`. */
|
|
2072
|
+
declare function dbAdd<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbAddArgs<T, As, Cols, A> & {
|
|
2073
|
+
asFilters?: Fs;
|
|
2074
|
+
}): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A>, Fs>>;
|
|
2075
|
+
interface DbEditArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
|
|
2076
|
+
/**
|
|
2077
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2078
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2079
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2080
|
+
*/
|
|
2081
|
+
tableAlias?: string;
|
|
2082
|
+
/**
|
|
2083
|
+
* Refuse to auto-wire request inputs the endpoint did not explicitly bind.
|
|
2084
|
+
*
|
|
2085
|
+
* A row write auto-wires any column whose name matches an incoming request
|
|
2086
|
+
* input, which is convenient and is also how a caller can reach a column the
|
|
2087
|
+
* endpoint never meant to expose. With this on, the engine consults the
|
|
2088
|
+
* endpoint's declared inputs and skips auto-wiring anything outside them;
|
|
2089
|
+
* explicit `data`/`row` entries are unaffected, because those are bindings you
|
|
2090
|
+
* wrote.
|
|
2091
|
+
*
|
|
2092
|
+
* Off by default, matching the engine's own default — so leaving it unset
|
|
2093
|
+
* writes nothing and changes nothing. Reach for it on any write whose table
|
|
2094
|
+
* has a column a caller must not set (`role`, `is_admin`, `credits`).
|
|
2095
|
+
*/
|
|
2096
|
+
enforceHiddenFields?: boolean;
|
|
2097
|
+
table: DbTableRef<T>;
|
|
2098
|
+
/** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
|
|
2099
|
+
fieldName?: QualifiedCol<ColsOf<T>>;
|
|
2100
|
+
fieldValue: Value;
|
|
2101
|
+
/** The new field values as explicit entries (exact control over each field + `ignore`). */
|
|
2102
|
+
data?: DbField[];
|
|
2103
|
+
/**
|
|
2104
|
+
* A **partial** row keyed by column name: only the columns you list are
|
|
2105
|
+
* written. Columns you omit are emitted with `ignore:true` and keep their
|
|
2106
|
+
* stored value — a `{ votes }` edit updates `votes` alone and leaves every
|
|
2107
|
+
* other column intact (issue #33). Expanded against the table's declared
|
|
2108
|
+
* columns. Use `data` for byte-exact control over each entry's `ignore` flag.
|
|
2109
|
+
*/
|
|
2110
|
+
row?: RowMap<ColsOf<T>, RowsOf<T>>;
|
|
2111
|
+
/**
|
|
2112
|
+
* Restrict the columns of the RETURNED row (XanoScript `output = [...]`) —
|
|
2113
|
+
* the confirmation response only; it does not change what is written. Same
|
|
2114
|
+
* customized envelope as {@link DbGetArgs.output}, and offered on exactly the
|
|
2115
|
+
* write ops whose result is a row rather than a scalar: the editor hides the
|
|
2116
|
+
* customize control when a statement's whole output is a single `bool`/`int`
|
|
2117
|
+
* scalar (`db.del`, `db.has`), which is why those take no `output`.
|
|
2118
|
+
*/
|
|
2119
|
+
output?: Cols;
|
|
2120
|
+
/** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
|
|
2121
|
+
* addon's alias (the last segment of its `as`) is merged onto the row shape in
|
|
2122
|
+
* `InferResponse` — typed from the addon's graft shape when it's a typed
|
|
2123
|
+
* `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
|
|
2124
|
+
addon?: A;
|
|
2125
|
+
/** Capture the post-mutation row into this stack variable. Captured literally so
|
|
2126
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
2127
|
+
as?: As;
|
|
2128
|
+
}
|
|
2129
|
+
/** `db.edit <table>` — update a record matched by a field (`mvp:dbo_editby`).
|
|
2130
|
+
* Binds the **full post-mutation row** (the freshly-written values), so it's
|
|
2131
|
+
* branded with `as` + the row shape for `InferResponse` (throws `NotFound`/404
|
|
2132
|
+
* when nothing matches). */
|
|
2133
|
+
declare function dbEdit<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbEditArgs<T, As, Cols, A> & {
|
|
2134
|
+
asFilters?: Fs;
|
|
2135
|
+
}): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A>, Fs>>;
|
|
2136
|
+
/**
|
|
2137
|
+
* `db.add_or_edit` (`mvp:dbo_addoreditby`) — upsert: edit the row matched by
|
|
2138
|
+
* `fieldName`/`fieldValue` if it exists, else insert. Its persisted fixture is a
|
|
2139
|
+
* *leaner* serialization generation than the `dbo_add`/`dbo_editby` family:
|
|
2140
|
+
*
|
|
2141
|
+
* - input entries are the lean `{name,value,tag,filters}` form (no
|
|
2142
|
+
* `expand`/`children`), and only the row `data` entries carry an `ignore`
|
|
2143
|
+
* flag — the `field_name`/`field_value` lookup pair never do;
|
|
2144
|
+
* - `context.dbo` additionally carries the table's `as` (its name) beside `id`;
|
|
2145
|
+
* - there is no rich `description`/`settings_registry`/`output`/`addon` envelope.
|
|
2146
|
+
*
|
|
2147
|
+
* Matched correct-by-construction against the golden, same posture as the rest
|
|
2148
|
+
* of the db family.
|
|
2149
|
+
*/
|
|
2150
|
+
interface DbAddOrEditArgs<T extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
|
|
2151
|
+
/**
|
|
2152
|
+
* Refuse to auto-wire request inputs the endpoint did not explicitly bind.
|
|
2153
|
+
*
|
|
2154
|
+
* A row write auto-wires any column whose name matches an incoming request
|
|
2155
|
+
* input, which is convenient and is also how a caller can reach a column the
|
|
2156
|
+
* endpoint never meant to expose. With this on, the engine consults the
|
|
2157
|
+
* endpoint's declared inputs and skips auto-wiring anything outside them;
|
|
2158
|
+
* explicit `data`/`row` entries are unaffected, because those are bindings you
|
|
2159
|
+
* wrote.
|
|
2160
|
+
*
|
|
2161
|
+
* Off by default, matching the engine's own default — so leaving it unset
|
|
2162
|
+
* writes nothing and changes nothing. Reach for it on any write whose table
|
|
2163
|
+
* has a column a caller must not set (`role`, `is_admin`, `credits`).
|
|
2164
|
+
*/
|
|
2165
|
+
enforceHiddenFields?: boolean;
|
|
2166
|
+
table: DbTableRef<T>;
|
|
2167
|
+
/** The match field (defaults to the primary key `id`). */
|
|
2168
|
+
/** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
|
|
2169
|
+
fieldName?: QualifiedCol<ColsOf<T>>;
|
|
2170
|
+
/** The value to match for the edit branch. */
|
|
2171
|
+
fieldValue: Value;
|
|
2172
|
+
/** The row to upsert as explicit entries (exact control over each field + `ignore`). */
|
|
2173
|
+
data?: DbField[];
|
|
2174
|
+
/** A partial row keyed by column name; expanded against the table's declared columns. */
|
|
2175
|
+
row?: RowMap<ColsOf<T>, RowsOf<T>>;
|
|
2176
|
+
/** Capture the upserted row into this stack variable. Captured literally so
|
|
2177
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
2178
|
+
as?: As;
|
|
2179
|
+
/**
|
|
2180
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2181
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2182
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2183
|
+
*/
|
|
2184
|
+
tableAlias?: string;
|
|
2185
|
+
}
|
|
2186
|
+
/** `db.add_or_edit <table>` — upsert a record by a field match (`mvp:dbo_addoreditby`).
|
|
2187
|
+
* Binds the **full upserted row** (`$inst->toArray()`, the edit-or-insert result),
|
|
2188
|
+
* so it's branded with `as` + the row shape for `InferResponse`. */
|
|
2189
|
+
declare function dbAddOrEdit<T extends ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbAddOrEditArgs<T, As> & {
|
|
2190
|
+
asFilters?: Fs;
|
|
2191
|
+
}): DbResult<As, ApplyFilters<FullRowShapeOf<T>, Fs>>;
|
|
2192
|
+
interface DbSchemaArgs extends StatementOptions {
|
|
2193
|
+
/**
|
|
2194
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2195
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2196
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2197
|
+
*/
|
|
2198
|
+
tableAlias?: string;
|
|
2199
|
+
table: DbTableRef;
|
|
2200
|
+
/** Dot-path into the schema to read. */
|
|
2201
|
+
path: Value;
|
|
2202
|
+
as?: string;
|
|
2203
|
+
}
|
|
2204
|
+
/** `db.schema <table>` — read a table's schema (`mvp:dbo_get_schema`). */
|
|
2205
|
+
declare function dbSchema(args: DbSchemaArgs): Statement;
|
|
2206
|
+
/**
|
|
2207
|
+
* Result shape of a raw-SQL query. The engine schema types this as open
|
|
2208
|
+
* `static:text` (default `"list"`); the known values are suggested while any
|
|
2209
|
+
* string remains accepted.
|
|
2210
|
+
*/
|
|
2211
|
+
type DbResponseType = "list" | "single" | (string & {});
|
|
2212
|
+
/**
|
|
2213
|
+
* How the SQL body is interpolated before it runs.
|
|
2214
|
+
*
|
|
2215
|
+
* `"prepared"` (the engine default) substitutes the positional `args` as bound
|
|
2216
|
+
* parameters. `"template_engine"` renders the body as a template first, which is
|
|
2217
|
+
* what lets a query interpolate structure — a column list, a table name — that a
|
|
2218
|
+
* bound parameter cannot carry. It changes how the statement executes, so it is
|
|
2219
|
+
* authored rather than inferred, and the key is written only when set: the
|
|
2220
|
+
* engine defaults it and omits it at the default.
|
|
2221
|
+
*/
|
|
2222
|
+
type DbSqlParser = "prepared" | "template_engine";
|
|
2223
|
+
interface DbDirectQueryArgs extends StatementOptions {
|
|
2224
|
+
/** The raw SQL to run (stored verbatim as `context.code`). */
|
|
2225
|
+
sql: string;
|
|
2226
|
+
/** Result shape: `"list"` (default) or `"single"`. */
|
|
2227
|
+
responseType?: DbResponseType;
|
|
2228
|
+
/** Positional bind arguments — each a tagged value (filters preserved). */
|
|
2229
|
+
args?: Value[];
|
|
2230
|
+
/** How the SQL body is interpolated. See {@link DbSqlParser}. */
|
|
2231
|
+
parser?: DbSqlParser;
|
|
2232
|
+
/** Capture the result into this stack variable. */
|
|
2233
|
+
as?: string;
|
|
2234
|
+
}
|
|
2235
|
+
/**
|
|
2236
|
+
* `db.direct_query` (`mvp:dbo_direct_query`) — execute raw SQL against the
|
|
2237
|
+
* workspace database. Unlike the `!map:dbo` family it references no table, so
|
|
2238
|
+
* `context` carries the SQL (`code`), the `response_type`, and the positional
|
|
2239
|
+
* `arg[]` bind values instead of a `dbo.id`. It keeps the same rich envelope.
|
|
2240
|
+
*/
|
|
2241
|
+
declare function dbDirectQuery(args: DbDirectQueryArgs): Statement;
|
|
2242
|
+
interface DbBulkAddArgs extends StatementOptions {
|
|
2243
|
+
/**
|
|
2244
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2245
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2246
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2247
|
+
*/
|
|
2248
|
+
tableAlias?: string;
|
|
2249
|
+
table: DbTableRef;
|
|
2250
|
+
/** The rows to insert (an array value). */
|
|
2251
|
+
items: Value;
|
|
2252
|
+
/**
|
|
2253
|
+
* Honor an explicit `id` on each row (`allow_id_field`).
|
|
2254
|
+
*
|
|
2255
|
+
* ⚠ **Unset/`false` means the engine STRIPS `id` from every item** and assigns
|
|
2256
|
+
* the next sequence value instead — silently, with no error and no warning.
|
|
2257
|
+
* The rows then sit at ids nothing else expects, which surfaces much later as
|
|
2258
|
+
* a foreign key pointing at the wrong row (issue #259).
|
|
2259
|
+
*
|
|
2260
|
+
* This is the opposite of a `table` `seed`, where supplying `id` pins it. If
|
|
2261
|
+
* you are inserting rows whose ids other rows reference, set this to `true`.
|
|
2262
|
+
* Set it to `false` explicitly to state that engine-assigned ids are intended.
|
|
2263
|
+
*/
|
|
2264
|
+
allowIdField?: boolean;
|
|
2265
|
+
as?: string;
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* `db.bulk.add <table>` — insert many rows (`mvp:dbo_bulkadd`).
|
|
2269
|
+
*
|
|
2270
|
+
* ⚠ An `id` on a row is DISCARDED unless {@link DbBulkAddArgs.allowIdField} is
|
|
2271
|
+
* `true` — see that field. Literal rows carrying one are rejected here rather
|
|
2272
|
+
* than silently renumbered by the engine (issue #259).
|
|
2273
|
+
*/
|
|
2274
|
+
declare function dbBulkAdd(args: DbBulkAddArgs): Statement;
|
|
2275
|
+
interface DbBulkDeleteArgs<As extends string = string> extends StatementOptions {
|
|
2276
|
+
/**
|
|
2277
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2278
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2279
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2280
|
+
*/
|
|
2281
|
+
tableAlias?: string;
|
|
2282
|
+
table: DbTableRef;
|
|
2283
|
+
/**
|
|
2284
|
+
* Filter selecting which rows to delete — the same `where` surface as
|
|
2285
|
+
* `s.db.query`: `expr(...)`/`cmp(...)` comparisons, `and(...)`/`or(...)` groups,
|
|
2286
|
+
* an array of those (ANDed), or a raw `Value`. Encoded into `context.search`
|
|
2287
|
+
* via {@link encodeSearch}. **A `where` that constrains nothing deletes every
|
|
2288
|
+
* row in the table**, which is why it requires {@link DbBulkDeleteArgs.allRows}.
|
|
2289
|
+
*/
|
|
2290
|
+
where?: DbWhere;
|
|
2291
|
+
/**
|
|
2292
|
+
* Delete EVERY row: the explicit opt-in a `where`-less bulk delete requires.
|
|
2293
|
+
*
|
|
2294
|
+
* A filter-less delete is a truncate, and the shape that reaches it — forgetting
|
|
2295
|
+
* the predicate — looks identical to the shape that meant it. Saying so costs one
|
|
2296
|
+
* word and cannot be typed by accident. Passing both this and a `where` is a
|
|
2297
|
+
* contradiction and throws.
|
|
2298
|
+
*
|
|
2299
|
+
* Emits an EMPTY-GROUP `context.search`, which is what the engine accepts as
|
|
2300
|
+
* "every row" — omitting the key entirely is refused with
|
|
2301
|
+
* `Missing param: search` (XTS-5). Use `s.db.truncate({ reset: true })` when
|
|
2302
|
+
* the id sequence should restart too; this one returns the deleted count.
|
|
2303
|
+
*/
|
|
2304
|
+
allRows?: true;
|
|
2305
|
+
/** Capture the deleted-row count into this stack variable. Captured literally so
|
|
2306
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
2307
|
+
as?: As;
|
|
2308
|
+
}
|
|
2309
|
+
/**
|
|
2310
|
+
* `db.bulk.delete <table>` — delete many rows by a search (`mvp:dbo_bulkdelete`).
|
|
2311
|
+
* Unlike the other bulk ops, the filter rides `context.search`,
|
|
2312
|
+
* NOT an input entry. The `where` is encoded through the shared {@link encodeSearch}
|
|
2313
|
+
* — the identical operand-based `{expression:[…]}` shape `s.db.query` emits — so the
|
|
2314
|
+
* modern DSL (`expr`/`cmp`/`and`/`or`) is fully supported here too.
|
|
2315
|
+
*
|
|
2316
|
+
* Golden-verified against a live capture: `context.search` (shared with the
|
|
2317
|
+
* `dbo_view` search reader) is byte-exact. A `where` that constrains nothing —
|
|
2318
|
+
* an empty `and()`/`or()` group — deletes all rows and returns the count; the
|
|
2319
|
+
* key itself is mandatory, so `allRows` supplies the empty group (XTS-5).
|
|
2320
|
+
*
|
|
2321
|
+
* Binds the **deleted-row count** (the engine's `__self: int` output), so it's
|
|
2322
|
+
* branded with `as` + `number` for `InferResponse` — table-independent.
|
|
2323
|
+
*/
|
|
2324
|
+
declare function dbBulkDelete<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbBulkDeleteArgs<As> & {
|
|
2325
|
+
asFilters?: Fs;
|
|
2326
|
+
}): DbResult<As, ApplyFilters<number, Fs>>;
|
|
2327
|
+
interface DbBulkWriteArgs<T extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
|
|
2328
|
+
/**
|
|
2329
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2330
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2331
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2332
|
+
*/
|
|
2333
|
+
tableAlias?: string;
|
|
2334
|
+
table: DbTableRef<T>;
|
|
2335
|
+
/** The rows to write (an array value), each carrying its key. */
|
|
2336
|
+
items: Value;
|
|
2337
|
+
/** Capture the result into this stack variable. Captured literally so
|
|
2338
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
2339
|
+
as?: As;
|
|
2340
|
+
}
|
|
2341
|
+
/** `db.bulk.patch <table>` — partial-update many rows (`mvp:dbo_bulkpatch`).
|
|
2342
|
+
* Binds the **patched-row LIST** (the engine's `__self[]` row output), so it's
|
|
2343
|
+
* branded with `as` + the row-list shape for `InferResponse`. */
|
|
2344
|
+
declare function dbBulkPatch<T extends ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbBulkWriteArgs<T, As> & {
|
|
2345
|
+
asFilters?: Fs;
|
|
2346
|
+
}): DbResult<As, ApplyFilters<FullRowShapeOf<T>[], Fs>>;
|
|
2347
|
+
/**
|
|
2348
|
+
* `db.bulk.update <table>` — REPLACE many rows (`mvp:dbo_bulkupdate`).
|
|
2349
|
+
*
|
|
2350
|
+
* ⚠ **Every column an item omits is written to its zero value** (`""` / `0` /
|
|
2351
|
+
* `null` / `[]` / `{}`), not left alone, with an HTTP 200 and no error. This is
|
|
2352
|
+
* a whole-row replace: `{ id: 7, status: "done" }` sets the status and blanks
|
|
2353
|
+
* every other column of row 7. Confirmed in the engine — update and patch run
|
|
2354
|
+
* the same code, and update writes each absent column's default.
|
|
2355
|
+
*
|
|
2356
|
+
* **Use {@link dbBulkPatch} (`s.db.bulk.patch`) to write only the keys an item
|
|
2357
|
+
* carries.** That is what "update these titles" means; this statement is for
|
|
2358
|
+
* replacing rows wholesale. `export()` warns when a STATIC `items` array omits
|
|
2359
|
+
* columns of the bound table, and `--strict` / `export({ strict: true })` fails
|
|
2360
|
+
* the build on it — but an `items` built from a `ref`/`inp` cannot be inspected,
|
|
2361
|
+
* so nothing catches that one for you (issue #15).
|
|
2362
|
+
*
|
|
2363
|
+
* Left **unbranded** (plain {@link Statement}): the engine declares no output
|
|
2364
|
+
* schema for `dbo_bulkupdate`/`dbo_bulkadd`, so
|
|
2365
|
+
* `InferResponse` faithfully resolves a returned bulk-add/update var to `unknown`
|
|
2366
|
+
* — matching where the engine's own OpenAPI walk falls back to `json`. Only
|
|
2367
|
+
* `bulk.patch` (row list) and `bulk.delete` (count) carry a static output schema.
|
|
2368
|
+
*/
|
|
2369
|
+
declare function dbBulkUpdate(args: DbBulkWriteArgs): Statement;
|
|
2370
|
+
/**
|
|
2371
|
+
* Paging controls for `db.query`. Static controls (`page`/`per_page`/`offset` as
|
|
2372
|
+
* plain numbers) land in `context.return.list.paging` (with `enabled:true`) and
|
|
2373
|
+
* mirror the engine schema's `return.list.paging` block: `page=1`, `per_page=25`,
|
|
2374
|
+
* `offset=0`, `totals=false`, `metadata=true`.
|
|
2375
|
+
*
|
|
2376
|
+
* **Input-bound (dynamic) paging (issue #66):** pass a {@link Value} (e.g.
|
|
2377
|
+
* `inp("page")`) for `page`/`per_page`/`offset` instead of a number and it is
|
|
2378
|
+
* emitted into `context.simpleExternal.<field>` as a tagged `{value,tag,filters}`
|
|
2379
|
+
* (byte shape from the `simpleExternal` golden — the inner key is `value`, not
|
|
2380
|
+
* `operand`), while the static block stays as the engine's baseline/fallback and
|
|
2381
|
+
* the gate (`enabled:true`). `search`/`sort` accept a {@link Value} for a
|
|
2382
|
+
* dynamic custom-query / sort override; the engine reads those unconditionally.
|
|
2383
|
+
*
|
|
2384
|
+
* The `enabled:true` gate is keyed on whether a **page/per_page/offset** field is
|
|
2385
|
+
* present (static or `Value`) — a `paging` object carrying *only* `search`/`sort`
|
|
2386
|
+
* leaves `enabled:false`, so a dynamic-search-only override does not silently
|
|
2387
|
+
* activate default pagination and truncate the result to 25 rows.
|
|
2388
|
+
*
|
|
2389
|
+
* Note `metadata:true` (the default) wraps the result in a paging envelope
|
|
2390
|
+
* (`{ items, curPage, nextPage, … }`) rather than returning a bare row list; pass
|
|
2391
|
+
* `metadata:false` to keep the bare array. The envelope only applies when a
|
|
2392
|
+
* page/per_page/offset field is present.
|
|
2393
|
+
*/
|
|
2394
|
+
interface DbPaging {
|
|
2395
|
+
page?: number | Value;
|
|
2396
|
+
per_page?: number | Value;
|
|
2397
|
+
offset?: number | Value;
|
|
2398
|
+
totals?: boolean;
|
|
2399
|
+
metadata?: boolean;
|
|
2400
|
+
/**
|
|
2401
|
+
* The engine's paging gate (`context.return.<type>.paging.enabled`).
|
|
2402
|
+
*
|
|
2403
|
+
* **Leave this unset.** It defaults to being DERIVED — on whenever a
|
|
2404
|
+
* `page`/`per_page`/`offset` field or a classic `external` blob is present —
|
|
2405
|
+
* which is what stops a `search`/`sort`-only `paging` from silently truncating a
|
|
2406
|
+
* result to 25 rows (issue #41). Setting it overrides that derivation.
|
|
2407
|
+
*
|
|
2408
|
+
* It exists because a stored query can carry the two apart: real workspaces
|
|
2409
|
+
* persist a non-default `per_page` with the gate OFF, and a derived-only encoder
|
|
2410
|
+
* cannot reproduce that — which cost ~158 `db.query` statements their
|
|
2411
|
+
* readability. So this is here to REPRESENT a stored state faithfully, like
|
|
2412
|
+
* `table: null`; authoring `enabled: false` beside a `per_page` asks the engine
|
|
2413
|
+
* to ignore that `per_page`.
|
|
2414
|
+
*
|
|
2415
|
+
* Note it also moves where addons graft: a metadata paging envelope puts rows
|
|
2416
|
+
* under `items[]`, so the gate and the addon offset stay consistent.
|
|
2417
|
+
*/
|
|
2418
|
+
enabled?: boolean;
|
|
2419
|
+
/** Dynamic custom-query override (`context.simpleExternal.search`) — a {@link Value}, ANDed onto the static `where`. */
|
|
2420
|
+
search?: Value;
|
|
2421
|
+
/** Dynamic sort override (`context.simpleExternal.sort`) — a {@link Value}; replaces the static sort at runtime. */
|
|
2422
|
+
sort?: Value;
|
|
2423
|
+
}
|
|
2424
|
+
/**
|
|
2425
|
+
* Which parts of a classic {@link DbExternal} blob the engine is permitted to
|
|
2426
|
+
* honor. Each defaults to the engine's own default (search/sort/page `true`,
|
|
2427
|
+
* `per_page` `false`) — the shape from the `external` golden.
|
|
2428
|
+
*/
|
|
2429
|
+
interface DbExternalPermissions {
|
|
2430
|
+
search?: boolean;
|
|
2431
|
+
sort?: boolean;
|
|
2432
|
+
page?: boolean;
|
|
2433
|
+
per_page?: boolean;
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* The classic single-blob external override (`context.external`). Its resolved
|
|
2437
|
+
* `value` is a whole faceted-filter object (`{search, sort, page, per_page}`),
|
|
2438
|
+
* typically fed from one request input; `permissions` gates which of those
|
|
2439
|
+
* sub-keys the engine honors.
|
|
2440
|
+
*
|
|
2441
|
+
* Combines with input-bound `paging` as a **fallback chain**: the engine uses
|
|
2442
|
+
* this blob when it resolves to something non-empty, and falls back to the
|
|
2443
|
+
* per-field `paging` binds when it does not. Supplying both is a working
|
|
2444
|
+
* configuration — an optional whole-config override in front of per-field
|
|
2445
|
+
* defaults — not a conflict.
|
|
2446
|
+
*/
|
|
2447
|
+
interface DbExternal {
|
|
2448
|
+
/** The whole external config as one tagged {@link Value} (e.g. `inp("filters")`). */
|
|
2449
|
+
value: Value;
|
|
2450
|
+
/** Per-part gates; each defaults to the engine default. */
|
|
2451
|
+
permissions?: DbExternalPermissions;
|
|
2452
|
+
}
|
|
2453
|
+
interface DbQueryArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T> | EvalAliases<E>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[], P extends DbPaging | undefined = DbPaging | undefined, RT extends DbReturnType = DbReturnType, E extends readonly DbEval[] = readonly DbEval[], AG extends DbAggregate = DbAggregate> extends StatementOptions {
|
|
2454
|
+
/**
|
|
2455
|
+
* SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
|
|
2456
|
+
* Absent unless set — Xano writes it on some statements and not others, so it
|
|
2457
|
+
* is authored rather than derived (see {@link dboBinding}).
|
|
2458
|
+
*/
|
|
2459
|
+
tableAlias?: string;
|
|
2460
|
+
table: DbTableRef<T>;
|
|
2461
|
+
/**
|
|
2462
|
+
* The engine's `context.return.type`. `"list"` (default) returns a row array
|
|
2463
|
+
* (or paging envelope); `"single"` a first-match `row | null`; `"count"` a
|
|
2464
|
+
* `number`; `"exists"` a `boolean`; `"stream"` a pageable `row[]` with no
|
|
2465
|
+
* metadata envelope. `InferResponse` reflects each shape.
|
|
2466
|
+
*/
|
|
2467
|
+
returnType?: RT;
|
|
2468
|
+
/** Primary filter — `expr(...)`, an array of `expr(...)` (ANDed), or a raw `Value`. */
|
|
2469
|
+
where?: DbWhere;
|
|
2470
|
+
/** Additional filter ANDed with `where` (same forms as `where`). */
|
|
2471
|
+
additionalWhere?: DbWhere;
|
|
2472
|
+
/**
|
|
2473
|
+
* Joins (`context.bind[]`) — `[{ table, as?, join?, where? }]`. Joined columns
|
|
2474
|
+
* are addressable by dotted path in `where`/`sort`/`eval`; the row shape is
|
|
2475
|
+
* unchanged (output columns still come from `output`/`eval`).
|
|
2476
|
+
*/
|
|
2477
|
+
bind?: DbBind[];
|
|
2478
|
+
/** Sort directives (`[{ sortBy, dir }]`) — applied by the engine. */
|
|
2479
|
+
sort?: SortDirective<ColsOf<T> | EvalAliases<E>>[];
|
|
2480
|
+
/** Acquire row locks. */
|
|
2481
|
+
lock?: boolean;
|
|
2482
|
+
/**
|
|
2483
|
+
* Paging controls (`page`/`per_page`/`offset`/`totals`/`metadata`) — applied by
|
|
2484
|
+
* the engine. **Supplying `paging` changes the response shape:** with metadata
|
|
2485
|
+
* on (the default) the result is wrapped in a paging envelope
|
|
2486
|
+
* (`{ items, curPage, nextPage, prevPage, offset, perPage, itemsReceived }`,
|
|
2487
|
+
* plus `itemsTotal`/`pageTotal` when `totals:true`) instead of a bare row list,
|
|
2488
|
+
* and `InferResponse` reflects that (issue #58). Pass `metadata:false` to keep
|
|
2489
|
+
* the bare array.
|
|
2490
|
+
*/
|
|
2491
|
+
paging?: P;
|
|
2492
|
+
/**
|
|
2493
|
+
* Classic single-blob external override (`context.external`) — one tagged
|
|
2494
|
+
* {@link Value} whose resolved value is a whole `{search,sort,page,per_page}`
|
|
2495
|
+
* config, with per-part `permissions` gates. Mutually exclusive with an
|
|
2496
|
+
* input-bound `paging` field (a `Value` page/per_page/offset/search/sort): the
|
|
2497
|
+
* engine honors `simpleExternal` only when `external` is empty, so authoring
|
|
2498
|
+
* both throws. Setting `external` forces `paging.enabled:true` so its
|
|
2499
|
+
* page/per_page take effect even with no `paging` arg.
|
|
2500
|
+
*/
|
|
2501
|
+
external?: DbExternal;
|
|
2502
|
+
/**
|
|
2503
|
+
* Distinct-row handling for a `list`/`stream` query (`"auto"` default | `"yes"`
|
|
2504
|
+
* | `"no"`) → `context.return.<type>.distinct`. Ignored for single/count/exists.
|
|
2505
|
+
*/
|
|
2506
|
+
distinct?: DbDistinct;
|
|
2507
|
+
/**
|
|
2508
|
+
* Computed output columns (`context.eval[]`) — each `{ name, as, filters? }`.
|
|
2509
|
+
* The `as` alias grafts onto every returned row as an `unknown`-typed key
|
|
2510
|
+
* (`InferResponse`), since a filter pipeline's output isn't statically knowable.
|
|
2511
|
+
* An alias shadowing an existing column throws at build time.
|
|
2512
|
+
*/
|
|
2513
|
+
eval?: E;
|
|
2514
|
+
/**
|
|
2515
|
+
* Aggregate/group-by config, used with `returnType:"aggregate"` →
|
|
2516
|
+
* `context.return.aggregate.{group,eval,sort,paging}`. `InferResponse` types the
|
|
2517
|
+
* aggregate row from the `group` and `eval` aliases (values `unknown`).
|
|
2518
|
+
*/
|
|
2519
|
+
aggregate?: AG;
|
|
2520
|
+
/** Restrict returned columns. Captured literally so `InferResponse` narrows
|
|
2521
|
+
* the traced row list to exactly these columns. */
|
|
2522
|
+
output?: Cols;
|
|
2523
|
+
/** Attach addons to enrich each returned row (see {@link AddonSpec}). Each
|
|
2524
|
+
* addon's alias (the last segment of its `as`) is merged onto the row shape in
|
|
2525
|
+
* `InferResponse` as an `unknown`-typed key — narrow it at the call site. Author
|
|
2526
|
+
* `as` relative to a row (`"_user"`); when the query returns a metadata paging
|
|
2527
|
+
* envelope, the `items[]` offset is prefixed automatically. */
|
|
2528
|
+
addon?: A;
|
|
2529
|
+
/** Capture the result list into this stack variable. Captured literally so
|
|
2530
|
+
* `InferResponse` can trace a `ref` back to this statement. */
|
|
2531
|
+
as?: As;
|
|
2532
|
+
}
|
|
2533
|
+
/**
|
|
2534
|
+
* `db.query <table>` — the query-all search builder (`mvp:dbo_view`). Emits the
|
|
2535
|
+
* context the engine actually reads:
|
|
2536
|
+
* the filter under `context.search` (`{expression:[…]}`, the same operand-based
|
|
2537
|
+
* shape as conditionals/trigger search), sort + paging under
|
|
2538
|
+
* `context.return.list`, and output-column restriction via the statement `output`
|
|
2539
|
+
* envelope. `where`/`sort`/`paging`/`output` are all applied by the engine.
|
|
2540
|
+
*
|
|
2541
|
+
* A comparison `where` (plus `additionalWhere`) encodes into one ANDed
|
|
2542
|
+
* `expression[]`; a raw `Value` is passed through as `context.search`.
|
|
2543
|
+
*/
|
|
2544
|
+
declare function dbQuery<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T> | EvalAliases<E>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const P extends DbPaging | undefined = undefined, const RT extends DbReturnType = "list", const E extends readonly DbEval[] = readonly [], const AG extends DbAggregate = DbAggregate, const Fs extends readonly FilterXdo[] = readonly []>(args: DbQueryArgs<T, As, Cols, A, P, RT, E, AG> & {
|
|
2545
|
+
asFilters?: Fs;
|
|
2546
|
+
}): DbResult<As, ApplyFilters<QueryResult<RowShapeOf<T, Cols>, A, P, RT, E, AG>, Fs>>;
|
|
2547
|
+
interface DbTransactionArgs extends StatementAnnotations {
|
|
2548
|
+
/** The statements to run atomically. */
|
|
2549
|
+
body: Statement[];
|
|
2550
|
+
/**
|
|
2551
|
+
* Capture the transaction's result into this stack variable.
|
|
2552
|
+
*
|
|
2553
|
+
* A transaction returns whatever its sub-stack returned, so the binding is
|
|
2554
|
+
* real state and not decoration — a pulled workspace stores one (issue #147).
|
|
2555
|
+
* The engine's XanoScript schema for this statement declares no `as`
|
|
2556
|
+
* argument, which is why nothing here modelled it; the statement class
|
|
2557
|
+
* returns a value all the same, and the stack item carries the binding like
|
|
2558
|
+
* any other.
|
|
2559
|
+
*/
|
|
2560
|
+
as?: string;
|
|
2561
|
+
}
|
|
2562
|
+
/**
|
|
2563
|
+
* `db.transaction { … }` — run a sub-stack in a database transaction
|
|
2564
|
+
* (`mvp:db_transaction`). Carries the `run` sub-stack and, where the author
|
|
2565
|
+
* bound one, the result variable. Byte-verified (parser-minimal) against the
|
|
2566
|
+
* engine's persisted shape.
|
|
2567
|
+
*/
|
|
2568
|
+
declare function dbTransaction(args: DbTransactionArgs): Statement;
|
|
2569
|
+
/** Supported external-SQL engines for `db.external.<engine>.direct_query`. */
|
|
2570
|
+
type ExternalSqlEngine = "mssql" | "mysql" | "oracle" | "postgres" | "snowflake";
|
|
2571
|
+
interface DbExternalQueryArgs extends StatementOptions {
|
|
2572
|
+
/** Which external database engine to target. */
|
|
2573
|
+
engine: ExternalSqlEngine;
|
|
2574
|
+
sql: string;
|
|
2575
|
+
/**
|
|
2576
|
+
* How to reach the external database. Prefer `env("NAME")` over a literal.
|
|
2577
|
+
*
|
|
2578
|
+
* A `Value` is stored as the tagged `context.connection_string_flex`, which is
|
|
2579
|
+
* what new work should write. A bare **string** is stored in the older
|
|
2580
|
+
* `context.connection_string` instead — the engine reads it as the name of a
|
|
2581
|
+
* workspace environment variable unless it already looks like a URL, and
|
|
2582
|
+
* falls back to it whenever the tagged value is empty. The two are separate
|
|
2583
|
+
* stored fields, so a workspace holding the older one round-trips as the older
|
|
2584
|
+
* one rather than being quietly rewritten (issue #138).
|
|
2585
|
+
*/
|
|
2586
|
+
connectionString: Value | string;
|
|
2587
|
+
responseType?: DbResponseType;
|
|
2588
|
+
args?: Value[];
|
|
2589
|
+
/** How the SQL body is interpolated. See {@link DbSqlParser}. */
|
|
2590
|
+
parser?: DbSqlParser;
|
|
2591
|
+
as?: string;
|
|
2592
|
+
}
|
|
2593
|
+
/**
|
|
2594
|
+
* `db.external.<engine>.direct_query' — raw SQL against an external database.
|
|
2595
|
+
* Stored shape from the engine's direct-query format (the shared base; these engines extend
|
|
2596
|
+
* it with `connection_string:true`): `context.{code, response_type,
|
|
2597
|
+
* connection_string_flex, arg[]}`. The connection string lands under
|
|
2598
|
+
* `connection_string_flex` (a tagged assignment value), NOT `connection_string`.
|
|
2599
|
+
*
|
|
2600
|
+
* Golden-verified against a live postgres capture: the engine persists
|
|
2601
|
+
* `context.{code,response_type,connection_string_flex,arg}` and does NOT store
|
|
2602
|
+
* `parser` at its default, so the SDK's omission is correct. The rich envelope
|
|
2603
|
+
* matches. @TODO(byte-verify): only postgres captured; the other 4 engines share
|
|
2604
|
+
* the format and stay modeled-by-analogy.
|
|
2605
|
+
*/
|
|
2606
|
+
declare function dbExternalQuery(args: DbExternalQueryArgs): Statement;
|
|
2607
|
+
|
|
2608
|
+
/**
|
|
2609
|
+
* Hand-authored typed wrappers for the HTTP-request statement family — the
|
|
2610
|
+
* "External API Request" (`api.request`) and its siblings `stream.from_request`
|
|
2611
|
+
* and `webflow.request`. Each has a generated bare-`Value`
|
|
2612
|
+
* factory because the codegen source YAML types every field as generic
|
|
2613
|
+
* `!kinds assign`; the engine's *runtime* schema is stricter (method enum, int
|
|
2614
|
+
* timeout, object params, string-array headers, booleans) and the frontend
|
|
2615
|
+
* enforces that shape. These wrappers surface ergonomic, literal-friendly types
|
|
2616
|
+
* (each still accepting a dynamic {@link Value}) and delegate encoding to the
|
|
2617
|
+
* generated factory, so the emitted statement stays byte-identical to the
|
|
2618
|
+
* generated path. Shared coercion + TLS validation live in {@link ./coerce.ts}.
|
|
2619
|
+
*
|
|
2620
|
+
* TLS/mTLS field interdependencies are validated at build time only when the
|
|
2621
|
+
* combination is statically provable-invalid (see `assertSslConsistency`); a
|
|
2622
|
+
* dynamic `Value` is never rejected. `description` (Settings tab) and `output`
|
|
2623
|
+
* (Output tab) ride the envelope where the statement carries one — today only
|
|
2624
|
+
* `api.request` does (its siblings are lean specs).
|
|
2625
|
+
*/
|
|
2626
|
+
|
|
2627
|
+
/**
|
|
2628
|
+
* The `{request, response}` envelope every external-request statement binds to
|
|
2629
|
+
* its `as` variable (`api.request`, `webflow.request`, `microservice.request`). Shape
|
|
2630
|
+
* confirmed against the Xano engine and a live run: `headers` are
|
|
2631
|
+
* arrays of raw `"Name: value"` lines, `result` is the response body (JSON-decoded
|
|
2632
|
+
* when possible, else the raw string — hence `unknown`), `status` the HTTP code,
|
|
2633
|
+
* and `error` is present only on a transport-level (curl) failure.
|
|
2634
|
+
*/
|
|
2635
|
+
interface ApiRequestResult {
|
|
2636
|
+
request: {
|
|
2637
|
+
url: string;
|
|
2638
|
+
method: string;
|
|
2639
|
+
headers: string[];
|
|
2640
|
+
params: unknown;
|
|
2641
|
+
};
|
|
2642
|
+
response: {
|
|
2643
|
+
headers: string[];
|
|
2644
|
+
result: unknown;
|
|
2645
|
+
status: number;
|
|
2646
|
+
error?: {
|
|
2647
|
+
code: number;
|
|
2648
|
+
message: string;
|
|
2649
|
+
};
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
interface ApiRequestArgs extends HttpRequestFields, StatementAnnotations {
|
|
2653
|
+
/** Capture the response (`{request, response}`) into this stack variable. */
|
|
2654
|
+
as?: string;
|
|
2655
|
+
/** Request URL. */
|
|
2656
|
+
url?: string | Value;
|
|
2657
|
+
/** Per-statement description (frontend "Settings" tab). */
|
|
2658
|
+
description?: string;
|
|
2659
|
+
/** Output-envelope shaping — result-variable filter chain / field mapping (frontend "Output" tab). */
|
|
2660
|
+
output?: OutputAuthored;
|
|
2661
|
+
}
|
|
2662
|
+
/**
|
|
2663
|
+
* `api.request` — issue an external HTTP request. Ergonomic, literal-friendly
|
|
2664
|
+
* field types over the generated `mvp:api_request` factory; delegates encoding
|
|
2665
|
+
* to it for byte-parity. Any field also accepts a dynamic {@link Value}.
|
|
2666
|
+
*
|
|
2667
|
+
* `method` suggests the 7 verbs, `params` is a key/value object (→ query string
|
|
2668
|
+
* for GET/HEAD/OPTIONS, body otherwise), `headers` an array of full header-line
|
|
2669
|
+
* strings, `timeout` seconds (engine bounds 1–86400), and the verify/follow
|
|
2670
|
+
* flags booleans.
|
|
2671
|
+
*
|
|
2672
|
+
* A plain-object `params` may carry tagged values (`inp`/`ref`/`c.*`) at the TOP
|
|
2673
|
+
* LEVEL only — each is lifted onto a `const:obj` via a `set` filter. Nest one
|
|
2674
|
+
* inside an object or array and encoding throws, because `const:obj` embeds a
|
|
2675
|
+
* plain JSON constant. For a body with any structure, wrap the whole thing in
|
|
2676
|
+
* `obj({...})`, which encodes any depth as a single `const:expr2`.
|
|
2677
|
+
*/
|
|
2678
|
+
declare function apiRequest<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a?: ApiRequestArgs & {
|
|
2679
|
+
as?: As;
|
|
2680
|
+
asFilters?: Fs;
|
|
2681
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<ApiRequestResult, Fs>>;
|
|
2682
|
+
interface StreamFromRequestArgs extends HttpRequestFields, StatementAnnotations {
|
|
2683
|
+
/** Capture the streaming response into this stack variable. */
|
|
2684
|
+
as?: string;
|
|
2685
|
+
/** Request URL. */
|
|
2686
|
+
url?: string | Value;
|
|
2687
|
+
}
|
|
2688
|
+
/**
|
|
2689
|
+
* `stream.from_request` — stream an external HTTP request (`mvp:streaming_api_request`).
|
|
2690
|
+
* Same typed field surface as {@link apiRequest}; delegates to the generated factory.
|
|
2691
|
+
*/
|
|
2692
|
+
declare function streamFromRequest(a?: StreamFromRequestArgs): Statement;
|
|
2693
|
+
interface WebflowRequestArgs extends HttpRequestFields, StatementAnnotations {
|
|
2694
|
+
/** Capture the response into this stack variable. */
|
|
2695
|
+
as?: string;
|
|
2696
|
+
/** Request path (relative to the Webflow API host). */
|
|
2697
|
+
path?: string | Value;
|
|
2698
|
+
}
|
|
2699
|
+
/**
|
|
2700
|
+
* `webflow.request` — call the Webflow API (`mvp:connect_webflow_api_request`).
|
|
2701
|
+
* Like {@link apiRequest} but addressed by `path` (the host is engine-supplied).
|
|
2702
|
+
*/
|
|
2703
|
+
declare function webflowRequest<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a?: WebflowRequestArgs & {
|
|
2704
|
+
as?: As;
|
|
2705
|
+
asFilters?: Fs;
|
|
2706
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<ApiRequestResult, Fs>>;
|
|
2707
|
+
|
|
2708
|
+
/**
|
|
2709
|
+
* `microservice.request` — call a container workload running alongside the
|
|
2710
|
+
* workspace (`mvp:microservice_request`).
|
|
2711
|
+
*
|
|
2712
|
+
* Its own module rather than a member of the external-HTTP-request family: a
|
|
2713
|
+
* microservice is a first-class workspace object with its own def factory and
|
|
2714
|
+
* its own deploy path, and this statement shares nothing with `api.request`
|
|
2715
|
+
* beyond the `{request, response}` result envelope — no TLS/cert fields, no
|
|
2716
|
+
* `output` envelope, and a different required-field contract (see
|
|
2717
|
+
* {@link MICROSERVICE_DEFAULTS}).
|
|
2718
|
+
*
|
|
2719
|
+
* The bulk of what lives here is host/port resolution: `host` and `port` are an
|
|
2720
|
+
* authoring convenience that folds into the single `"name:port"` string the
|
|
2721
|
+
* engine actually reads, and everything provably wrong about that pairing is
|
|
2722
|
+
* thrown on at build time rather than left to fail at request time.
|
|
2723
|
+
*/
|
|
2724
|
+
|
|
2725
|
+
/** Host spellings `s.microservice.request` accepts. */
|
|
2726
|
+
type MicroserviceHost = MicroserviceDef | string | Value;
|
|
2727
|
+
/**
|
|
2728
|
+
* The literal `servicePort`s a def declares, at the type level — the type-side
|
|
2729
|
+
* mirror of {@link declaredServicePorts}.
|
|
2730
|
+
*/
|
|
2731
|
+
type PortsOf<D> = D extends {
|
|
2732
|
+
deployment: {
|
|
2733
|
+
containers: readonly (infer C)[];
|
|
2734
|
+
};
|
|
2735
|
+
} ? C extends {
|
|
2736
|
+
ports: readonly (infer P)[];
|
|
2737
|
+
} ? P extends {
|
|
2738
|
+
servicePort: infer S extends string;
|
|
2739
|
+
} ? S : never : never : never;
|
|
2740
|
+
/** `"8080"` → `8080`, so a port may be written as a number. */
|
|
2741
|
+
type AsNumber<S extends string> = S extends `${infer N extends number}` ? N : never;
|
|
2742
|
+
/**
|
|
2743
|
+
* What `port` accepts for a given `host`.
|
|
2744
|
+
*
|
|
2745
|
+
* Constrained to the declared ports ONLY when they are known as literals. Two
|
|
2746
|
+
* cases deliberately fall back to the open type rather than narrowing to
|
|
2747
|
+
* `never`, because a false type error on valid code is worse than a missing
|
|
2748
|
+
* one: a def whose ports widened to `string` (annotated `MicroserviceDef`,
|
|
2749
|
+
* built dynamically), and a def that declares no ports at all (helm).
|
|
2750
|
+
*/
|
|
2751
|
+
type PortArg<D> = string extends PortsOf<D> ? number | string : [PortsOf<D>] extends [never] ? number | string : PortsOf<D> | AsNumber<PortsOf<D>>;
|
|
2752
|
+
/**
|
|
2753
|
+
* The five request fields this statement shares with the external-HTTP family,
|
|
2754
|
+
* taken FROM that family's field set rather than restated.
|
|
2755
|
+
*
|
|
2756
|
+
* The two declarations used to be typed byte-for-byte identically in two files,
|
|
2757
|
+
* and the cost showed up the first time one of them widened: the `headers`
|
|
2758
|
+
* record form (issue #72) had to be hand-added in both places, and missing the
|
|
2759
|
+
* second would have left the record spelling silently unavailable here (issue
|
|
2760
|
+
* #92). The per-field docs stay local because the DEFAULTS differ — this
|
|
2761
|
+
* statement's block schema requires all five, so it emits them (see
|
|
2762
|
+
* {@link MICROSERVICE_DEFAULTS}) where `api.request` may leave them out.
|
|
2763
|
+
*/
|
|
2764
|
+
type HttpFields = Pick<HttpRequestFields, "method" | "params" | "headers" | "timeout" | "follow_location">;
|
|
2765
|
+
interface MicroserviceArgs<H extends MicroserviceHost = MicroserviceHost> extends StatementOptions {
|
|
2766
|
+
/** Capture the response into this stack variable. */
|
|
2767
|
+
as?: string;
|
|
2768
|
+
/**
|
|
2769
|
+
* Target microservice — the `microservice()` def to call.
|
|
2770
|
+
*
|
|
2771
|
+
* A plain string is also accepted, and is the only way to reach an
|
|
2772
|
+
* instance-level microservice (those live in instance settings, not the
|
|
2773
|
+
* workspace, so there is no def to pass). It carries its own port:
|
|
2774
|
+
* `"legacy:80"`.
|
|
2775
|
+
*/
|
|
2776
|
+
host: H;
|
|
2777
|
+
/**
|
|
2778
|
+
* Port to call, folded into `host` as `name:port`.
|
|
2779
|
+
*
|
|
2780
|
+
* Optional: a microservice declaring exactly one `servicePort` resolves to it.
|
|
2781
|
+
* One declaring several requires this field, and rejects a port it does not
|
|
2782
|
+
* expose — as a TYPE error when the def's ports are known as literals, and as
|
|
2783
|
+
* a build-time throw otherwise. Serialized as text, matching how
|
|
2784
|
+
* `servicePort` is stored.
|
|
2785
|
+
*/
|
|
2786
|
+
port?: H extends MicroserviceDef ? PortArg<H> : number | string;
|
|
2787
|
+
/** Request path. */
|
|
2788
|
+
path: string | Value;
|
|
2789
|
+
/** HTTP verb — the 7 engine verbs are suggested; any string or dynamic `Value` is accepted. Defaults to `"GET"`. */
|
|
2790
|
+
method?: HttpFields["method"];
|
|
2791
|
+
/** Request params — a key/value object. Defaults to `{}`. */
|
|
2792
|
+
params?: HttpFields["params"];
|
|
2793
|
+
/** Headers — a `{ Name: value }` record (values may be tagged) or an array of full header-line strings. Defaults to `[]`. */
|
|
2794
|
+
headers?: HttpFields["headers"];
|
|
2795
|
+
/** Request timeout in seconds. Defaults to `10`. */
|
|
2796
|
+
timeout?: HttpFields["timeout"];
|
|
2797
|
+
/** Follow HTTP redirects. Defaults to `true`. */
|
|
2798
|
+
follow_location?: HttpFields["follow_location"];
|
|
2799
|
+
}
|
|
2800
|
+
/**
|
|
2801
|
+
* `microservice.request` — call an in-cluster microservice
|
|
2802
|
+
* (`mvp:microservice_request`). Typed over the generated factory; no TLS/cert
|
|
2803
|
+
* fields (the engine schema omits them).
|
|
2804
|
+
*
|
|
2805
|
+
* Only `host` and `path` are required. `method`, `params`, `headers`, `timeout`,
|
|
2806
|
+
* and `follow_location` default to the engine's own values
|
|
2807
|
+
* ({@link MICROSERVICE_DEFAULTS}) and are always EMITTED — this statement's
|
|
2808
|
+
* block schema requires them, so they cannot simply be left out:
|
|
2809
|
+
*
|
|
2810
|
+
* ```ts
|
|
2811
|
+
* s.microservice.request({ as: "result", host: echoService, path: "/health" })
|
|
2812
|
+
* ```
|
|
2813
|
+
*
|
|
2814
|
+
* Address it by passing the `microservice()` def itself — its declared ports are
|
|
2815
|
+
* then checked at the authoring site, and a rename fixes every call site at once:
|
|
2816
|
+
*
|
|
2817
|
+
* ```ts
|
|
2818
|
+
* s.microservice.request({ host: echoService, path: "/health", ... })
|
|
2819
|
+
* ```
|
|
2820
|
+
*
|
|
2821
|
+
* `host` binds by NAME, not by guid — deliberately, because the engine resolves
|
|
2822
|
+
* this field by name too (a workspace-scoped lookup on the microservice's name).
|
|
2823
|
+
* A guid here would not be merely unconventional; it would be wrong.
|
|
2824
|
+
*/
|
|
2825
|
+
declare function microserviceRequest<const As extends string = "", const H extends MicroserviceHost = MicroserviceHost, const Fs extends readonly FilterXdo[] = readonly []>(a: MicroserviceArgs<H> & {
|
|
2826
|
+
as?: As;
|
|
2827
|
+
} & {
|
|
2828
|
+
asFilters?: Fs;
|
|
2829
|
+
}): Statement & AsShapeBrand<As, ApplyFilters<ApiRequestResult, Fs>>;
|
|
2830
|
+
|
|
2831
|
+
/**
|
|
2832
|
+
* Typed `precondition` / `throw` overrides (issue #21).
|
|
2833
|
+
*
|
|
2834
|
+
* `s.throw` raises a generic error the runtime returns with **HTTP 200** and an
|
|
2835
|
+
* error body — a client checking `res.ok` (or any non-2xx guard) treats a
|
|
2836
|
+
* deliberately-thrown error as success. `s.precondition` instead maps its
|
|
2837
|
+
* `error_type` to a status-bearing exception (400/401/403/404/429/…), so a
|
|
2838
|
+
* boundary rejection is observable via standard HTTP semantics.
|
|
2839
|
+
*
|
|
2840
|
+
* Both delegate to the codegen'd factory — the encoded statement is identical —
|
|
2841
|
+
* and only narrow/annotate the authoring types. `error_type` in particular ships
|
|
2842
|
+
* from codegen as a bare `string`; here it becomes the engine's enum so the
|
|
2843
|
+
* valid values (and the status each yields) are discoverable at the call site.
|
|
2844
|
+
*/
|
|
2845
|
+
|
|
2846
|
+
/**
|
|
2847
|
+
* The exception a failed {@link precondition} raises, and the HTTP status the
|
|
2848
|
+
* runtime returns for it. Mirrors the engine's `mvp:precondition` `error_type`
|
|
2849
|
+
* enum ({@link https://github.com/xanots/sdk/issues/21 #21}):
|
|
2850
|
+
*
|
|
2851
|
+
* - `standard` — generic error (the default).
|
|
2852
|
+
* - `badrequest` — **400** Bad Request.
|
|
2853
|
+
* - `inputerror` — **400** Bad Request, tagged as input validation (the
|
|
2854
|
+
* `payload` is attached as the offending param).
|
|
2855
|
+
* - `unauthorized` — **401** Unauthorized.
|
|
2856
|
+
* - `accessdenied` — **403** Forbidden.
|
|
2857
|
+
* - `notfound` — **404** Not Found.
|
|
2858
|
+
* - `toomanyrequests` — **429** Too Many Requests.
|
|
2859
|
+
*/
|
|
2860
|
+
declare const PRECONDITION_ERROR_TYPES: readonly ["standard", "notfound", "toomanyrequests", "accessdenied", "unauthorized", "badrequest", "inputerror"];
|
|
2861
|
+
type PreconditionErrorType = (typeof PRECONDITION_ERROR_TYPES)[number];
|
|
2862
|
+
interface PreconditionArgs extends StatementAnnotations {
|
|
2863
|
+
/** The condition that must hold. When it evaluates falsy, the error is raised. */
|
|
2864
|
+
expr?: Condition;
|
|
2865
|
+
/**
|
|
2866
|
+
* Which status-bearing exception to raise on failure (default `standard`). Use
|
|
2867
|
+
* e.g. `badrequest` / `inputerror` to reject invalid input with a **400** a
|
|
2868
|
+
* client can detect via `res.ok` — unlike `s.throw`, which returns 200.
|
|
2869
|
+
*/
|
|
2870
|
+
error_type?: PreconditionErrorType;
|
|
2871
|
+
/**
|
|
2872
|
+
* The error message. ⚠ **Use `c.text("…")`, not a bare string.**
|
|
2873
|
+
*
|
|
2874
|
+
* The engine reads this field as a TAGGED value and falls back to the generic
|
|
2875
|
+
* `"Precondition failed."` whenever what it reads is empty or non-scalar — so
|
|
2876
|
+
* a bare string is dropped and the client never sees the message you wrote.
|
|
2877
|
+
* A `c.text(...)` (or any computed {@link Value}) is delivered intact. The
|
|
2878
|
+
* `error_type` → HTTP status mapping is correct either way; it is only the
|
|
2879
|
+
* message that is lost.
|
|
2880
|
+
*
|
|
2881
|
+
* The bare-string form stays accepted because a pulled workspace can carry
|
|
2882
|
+
* one and has to round-trip, not because it is a spelling to choose.
|
|
2883
|
+
*/
|
|
2884
|
+
error?: Value | string;
|
|
2885
|
+
/** Extra payload attached to the error (for `inputerror`, the offending param). */
|
|
2886
|
+
payload?: Value;
|
|
2887
|
+
}
|
|
2888
|
+
/**
|
|
2889
|
+
* `precondition { … }` — assert a condition and raise a **status-bearing** error
|
|
2890
|
+
* if it fails (`mvp:precondition`). Prefer this over {@link throwError} (`s.throw`)
|
|
2891
|
+
* whenever the rejection must be observable via HTTP status — a client guarding
|
|
2892
|
+
* on `res.ok` sees a real 4xx instead of a 200 with an error body. See issue #21.
|
|
2893
|
+
*
|
|
2894
|
+
* @example
|
|
2895
|
+
* s.precondition({
|
|
2896
|
+
* expr: fl.starts_with(input.url, "http"),
|
|
2897
|
+
* error_type: "badrequest",
|
|
2898
|
+
* error: c.text("url must start with http:// or https://"),
|
|
2899
|
+
* })
|
|
2900
|
+
*/
|
|
2901
|
+
declare function precondition(a?: PreconditionArgs): Statement;
|
|
2902
|
+
interface ThrowArgs extends StatementAnnotations {
|
|
2903
|
+
/** Optional error name/code. */
|
|
2904
|
+
name?: string;
|
|
2905
|
+
/** The error value/message. */
|
|
2906
|
+
value: Value;
|
|
2907
|
+
}
|
|
2908
|
+
/**
|
|
2909
|
+
* `throw <value>` — raise an error from the stack (`mvp:throw_error`).
|
|
2910
|
+
*
|
|
2911
|
+
* ⚠️ The runtime returns a thrown error with **HTTP 200** and an error body, so
|
|
2912
|
+
* a client checking `res.ok` treats it as success. For a rejection that surfaces
|
|
2913
|
+
* as a real 4xx status, use {@link precondition} (`s.precondition`) with an
|
|
2914
|
+
* `error_type`. See issue #21.
|
|
2915
|
+
*/
|
|
2916
|
+
declare function throwError(a: ThrowArgs): Statement;
|
|
2917
|
+
|
|
2918
|
+
/**
|
|
2919
|
+
* Typed overrides for statement args the engine declares as a CLOSED SET but the
|
|
2920
|
+
* codegen ships as a bare `string` (issue #65).
|
|
2921
|
+
*
|
|
2922
|
+
* The generated catalog harvests `enum` from the engine's runtime INPUT schemas,
|
|
2923
|
+
* so a closed set declared on a `context`-routed field arrives untyped. Both
|
|
2924
|
+
* fields here are context-routed, which is why they slipped through: the engine
|
|
2925
|
+
* states the members plainly, the SDK's types did not, and a typo type-checked,
|
|
2926
|
+
* exported, and deployed before misbehaving on a live environment.
|
|
2927
|
+
*
|
|
2928
|
+
* `access` is the sharp case. It defaults to `public`, so a misspelled
|
|
2929
|
+
* `"private"` does not fail closed — it serves the file to the world. That is
|
|
2930
|
+
* the wrong direction to fail in, and it was reachable with no compile-time
|
|
2931
|
+
* signal and no documented value list.
|
|
2932
|
+
*
|
|
2933
|
+
* Same shape as {@link ../special/precondition.ts}: delegate to the codegen'd
|
|
2934
|
+
* factory so the encoded statement is byte-identical, and narrow only the
|
|
2935
|
+
* authoring type. The member arrays are exported and consumed by the manifest
|
|
2936
|
+
* renderer (`CONTEXT_FIELD_ENUMS`), so the shipped types and the rendered
|
|
2937
|
+
* catalog line cannot drift from each other.
|
|
2938
|
+
*/
|
|
2939
|
+
|
|
2940
|
+
/**
|
|
2941
|
+
* Who can read a file created by the `s.storage.create_*` family.
|
|
2942
|
+
*
|
|
2943
|
+
* - `public` — world-readable by URL (**the engine's default**).
|
|
2944
|
+
* - `private` — reachable only through a signed URL
|
|
2945
|
+
* (`s.storage.sign_private_url`).
|
|
2946
|
+
*
|
|
2947
|
+
* Mirrors the engine's `access` enum on `mvp:create_attachment`,
|
|
2948
|
+
* `mvp:create_audio`, `mvp:create_image` and `mvp:create_video`.
|
|
2949
|
+
*/
|
|
2950
|
+
declare const STORAGE_ACCESS: readonly ["public", "private"];
|
|
2951
|
+
type StorageAccess = (typeof STORAGE_ACCESS)[number];
|
|
2952
|
+
/**
|
|
2953
|
+
* What `s.util.set_header` does when the header it sets is already present.
|
|
2954
|
+
*
|
|
2955
|
+
* - `replace` — overwrite the existing value (**the engine's default**).
|
|
2956
|
+
* - `append` — add another value, keeping the existing one.
|
|
2957
|
+
*
|
|
2958
|
+
* Mirrors the engine's `duplicates` enum on `mvp:setheader`.
|
|
2959
|
+
*/
|
|
2960
|
+
declare const HEADER_DUPLICATES: readonly ["replace", "append"];
|
|
2961
|
+
type HeaderDuplicates = (typeof HEADER_DUPLICATES)[number];
|
|
2962
|
+
/** `access` narrowed on a generated `storage.create_*` factory. */
|
|
2963
|
+
type WithAccess<T> = Omit<T, "access"> & {
|
|
2964
|
+
access?: StorageAccess;
|
|
2965
|
+
};
|
|
2966
|
+
type CreateAttachmentArgs = WithAccess<Parameters<typeof generated.storage.create_attachment>[0]>;
|
|
2967
|
+
type CreateAudioArgs = WithAccess<Parameters<typeof generated.storage.create_audio>[0]>;
|
|
2968
|
+
type CreateImageArgs = WithAccess<Parameters<typeof generated.storage.create_image>[0]>;
|
|
2969
|
+
type CreateVideoArgs = WithAccess<Parameters<typeof generated.storage.create_video>[0]>;
|
|
2970
|
+
type SetHeaderArgs = Omit<Parameters<typeof generated.util.set_header>[0], "duplicates"> & {
|
|
2971
|
+
duplicates?: HeaderDuplicates;
|
|
2972
|
+
};
|
|
2973
|
+
/**
|
|
2974
|
+
* `create_attachment` — store an uploaded file resource as an attachment.
|
|
2975
|
+
*
|
|
2976
|
+
* ⚠ `access` defaults to `"public"` (world-readable by URL). Pass
|
|
2977
|
+
* `access: "private"` and reach the file through `s.storage.sign_private_url`
|
|
2978
|
+
* when it must not be.
|
|
2979
|
+
*/
|
|
2980
|
+
declare function createAttachment(a: CreateAttachmentArgs): Statement;
|
|
2981
|
+
/**
|
|
2982
|
+
* `create_audio` — store an uploaded file resource as audio metadata.
|
|
2983
|
+
*
|
|
2984
|
+
* ⚠ `access` defaults to `"public"` (world-readable by URL).
|
|
2985
|
+
*/
|
|
2986
|
+
declare function createAudio(a: CreateAudioArgs): Statement;
|
|
2987
|
+
/**
|
|
2988
|
+
* `create_image` — store an uploaded file resource as image metadata.
|
|
2989
|
+
*
|
|
2990
|
+
* ⚠ `access` defaults to `"public"` (world-readable by URL).
|
|
2991
|
+
*/
|
|
2992
|
+
declare function createImage(a: CreateImageArgs): Statement;
|
|
2993
|
+
/**
|
|
2994
|
+
* `create_video` — store an uploaded file resource as video metadata.
|
|
2995
|
+
*
|
|
2996
|
+
* ⚠ `access` defaults to `"public"` (world-readable by URL).
|
|
2997
|
+
*/
|
|
2998
|
+
declare function createVideo(a: CreateVideoArgs): Statement;
|
|
2999
|
+
/**
|
|
3000
|
+
* `set_header` — set a response header. `duplicates` decides what happens when
|
|
3001
|
+
* the header is already present: `replace` (the default) overwrites it,
|
|
3002
|
+
* `append` adds another value alongside it.
|
|
3003
|
+
*/
|
|
3004
|
+
declare function setHeader(a: SetHeaderArgs): Statement;
|
|
3005
|
+
|
|
3006
|
+
/**
|
|
3007
|
+
* Typed refusal of `capture` on `s.lambda` (issue #73).
|
|
3008
|
+
*
|
|
3009
|
+
* The grounding docs introduce an inline `code:` arrow and then, several
|
|
3010
|
+
* paragraphs later, `lam.fn(fn, { surface?, capture? })`. Nothing connected the
|
|
3011
|
+
* two, so `capture` read as a property of lambda bodies generally. The bare
|
|
3012
|
+
* "does not exist in type" error that produced implies the WRONG fix — drop the
|
|
3013
|
+
* field — when the right one is to move the body into `lam.fn`.
|
|
3014
|
+
*
|
|
3015
|
+
* Naming the field and pointing at `lam.fn` costs nothing at runtime: the
|
|
3016
|
+
* factory delegates unchanged, so the encoded statement is byte-identical.
|
|
3017
|
+
*/
|
|
3018
|
+
|
|
3019
|
+
type LambdaArgs = Parameters<typeof generated.lambda>[0] & {
|
|
3020
|
+
/**
|
|
3021
|
+
* @deprecated Not a field of `s.lambda`. `capture` is an option of `lam.fn` —
|
|
3022
|
+
* move the body there: `code: lam.fn(fn, { capture: { … } })`.
|
|
3023
|
+
*
|
|
3024
|
+
* An inline `code:` arrow receives bindings only, so there is no slot here to
|
|
3025
|
+
* pass data through. Relocate the body; do not drop the field.
|
|
3026
|
+
*/
|
|
3027
|
+
capture?: never;
|
|
3028
|
+
};
|
|
3029
|
+
/**
|
|
3030
|
+
* `lambda { … }` — run a JavaScript body (`mvp:lambda`).
|
|
3031
|
+
*
|
|
3032
|
+
* Delegates to the generated factory unchanged. The only addition is a typed
|
|
3033
|
+
* refusal of `capture` (issue #73): the grounding docs introduce an inline
|
|
3034
|
+
* `code:` arrow and then `lam.fn(fn, { capture })` several paragraphs later, so
|
|
3035
|
+
* `capture` reads as a property of lambda bodies generally. The bare
|
|
3036
|
+
* "does not exist in type" error that produced implies the wrong fix — drop the
|
|
3037
|
+
* field — when the right one is to move the body into `lam.fn`. Naming it here
|
|
3038
|
+
* costs nothing at runtime and puts the answer in the error.
|
|
3039
|
+
*/
|
|
3040
|
+
declare function lambda(a?: LambdaArgs): Statement;
|
|
3041
|
+
|
|
3042
|
+
declare const s: {
|
|
3043
|
+
readonly precondition: typeof precondition;
|
|
3044
|
+
readonly throw: typeof throwError;
|
|
3045
|
+
readonly lambda: typeof lambda;
|
|
3046
|
+
readonly set_var: typeof setVar;
|
|
3047
|
+
readonly update_var: typeof updateVar;
|
|
3048
|
+
readonly conditional: typeof conditional;
|
|
3049
|
+
readonly comment: typeof comment;
|
|
3050
|
+
readonly for: typeof forLoop;
|
|
3051
|
+
readonly foreach: typeof foreachLoop;
|
|
3052
|
+
readonly while: typeof whileLoop;
|
|
3053
|
+
readonly group: typeof group;
|
|
3054
|
+
readonly switch: typeof switchStatement;
|
|
3055
|
+
readonly try_catch: typeof tryCatch;
|
|
3056
|
+
readonly return: typeof returnValue;
|
|
3057
|
+
readonly foreach_break: typeof foreachBreak;
|
|
3058
|
+
readonly foreach_continue: typeof foreachContinue;
|
|
3059
|
+
readonly foreach_remove: typeof foreachRemove;
|
|
3060
|
+
readonly function: {
|
|
3061
|
+
readonly run: typeof functionRun;
|
|
3062
|
+
readonly call: typeof functionCall;
|
|
3063
|
+
};
|
|
3064
|
+
readonly action: {
|
|
3065
|
+
readonly call: typeof actionCall;
|
|
3066
|
+
readonly package: {
|
|
3067
|
+
readonly call: typeof actionPackageCall;
|
|
3068
|
+
};
|
|
3069
|
+
};
|
|
3070
|
+
readonly workflow_test: {
|
|
3071
|
+
readonly call: typeof workflowTestCall;
|
|
3072
|
+
};
|
|
3073
|
+
readonly api: {
|
|
3074
|
+
readonly call: typeof apiCall;
|
|
3075
|
+
readonly realtime_event: typeof realtimeEvent;
|
|
3076
|
+
readonly request: typeof apiRequest;
|
|
3077
|
+
readonly stream: (a: {
|
|
3078
|
+
value: Value;
|
|
3079
|
+
disabled?: boolean;
|
|
3080
|
+
description?: string;
|
|
3081
|
+
}) => Statement;
|
|
3082
|
+
};
|
|
3083
|
+
readonly microservice: {
|
|
3084
|
+
readonly request: typeof microserviceRequest;
|
|
3085
|
+
};
|
|
3086
|
+
readonly realtime: {
|
|
3087
|
+
readonly publish: typeof realtimePublish;
|
|
3088
|
+
readonly get_session: (a?: {
|
|
3089
|
+
as?: string;
|
|
3090
|
+
disabled?: boolean;
|
|
3091
|
+
description?: string;
|
|
3092
|
+
asFilters?: FilterXdo[];
|
|
3093
|
+
}) => Statement;
|
|
3094
|
+
};
|
|
3095
|
+
readonly stream: {
|
|
3096
|
+
readonly from_request: typeof streamFromRequest;
|
|
3097
|
+
readonly from_csv: (a: {
|
|
3098
|
+
as?: string;
|
|
3099
|
+
value: Value;
|
|
3100
|
+
separator?: Value;
|
|
3101
|
+
enclosure?: Value;
|
|
3102
|
+
escape_char?: Value;
|
|
3103
|
+
disabled?: boolean;
|
|
3104
|
+
description?: string;
|
|
3105
|
+
asFilters?: FilterXdo[];
|
|
3106
|
+
output?: OutputAuthored;
|
|
3107
|
+
}) => Statement;
|
|
3108
|
+
readonly from_jsonl: (a: {
|
|
3109
|
+
as?: string;
|
|
3110
|
+
value: Value;
|
|
3111
|
+
disabled?: boolean;
|
|
3112
|
+
description?: string;
|
|
3113
|
+
asFilters?: FilterXdo[];
|
|
3114
|
+
}) => Statement;
|
|
3115
|
+
};
|
|
3116
|
+
readonly webflow: {
|
|
3117
|
+
readonly request: typeof webflowRequest;
|
|
3118
|
+
};
|
|
3119
|
+
readonly task: {
|
|
3120
|
+
readonly call: typeof taskCall;
|
|
3121
|
+
};
|
|
3122
|
+
readonly tool: {
|
|
3123
|
+
readonly call: typeof toolCall;
|
|
3124
|
+
};
|
|
3125
|
+
readonly trigger: {
|
|
3126
|
+
readonly call: typeof triggerCall;
|
|
3127
|
+
};
|
|
3128
|
+
readonly middleware: {
|
|
3129
|
+
readonly call: typeof middlewareCall;
|
|
3130
|
+
};
|
|
3131
|
+
readonly addon: {
|
|
3132
|
+
readonly call: typeof addonCall;
|
|
3133
|
+
};
|
|
3134
|
+
readonly db: {
|
|
3135
|
+
readonly add: typeof dbAdd;
|
|
3136
|
+
readonly edit: typeof dbEdit;
|
|
3137
|
+
readonly add_or_edit: typeof dbAddOrEdit;
|
|
3138
|
+
readonly get: typeof dbGet;
|
|
3139
|
+
readonly get_by_id: typeof dbGetById;
|
|
3140
|
+
readonly del: typeof dbDel;
|
|
3141
|
+
readonly has: typeof dbHas;
|
|
3142
|
+
readonly patch: typeof dbPatch;
|
|
3143
|
+
readonly truncate: typeof dbTruncate;
|
|
3144
|
+
readonly schema: typeof dbSchema;
|
|
3145
|
+
readonly direct_query: typeof dbDirectQuery;
|
|
3146
|
+
readonly query: typeof dbQuery;
|
|
3147
|
+
readonly transaction: typeof dbTransaction;
|
|
3148
|
+
readonly bulk: {
|
|
3149
|
+
readonly add: typeof dbBulkAdd;
|
|
3150
|
+
readonly delete: typeof dbBulkDelete;
|
|
3151
|
+
readonly patch: typeof dbBulkPatch;
|
|
3152
|
+
readonly update: typeof dbBulkUpdate;
|
|
3153
|
+
};
|
|
3154
|
+
readonly external: {
|
|
3155
|
+
readonly mssql: {
|
|
3156
|
+
direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
|
|
3157
|
+
};
|
|
3158
|
+
readonly mysql: {
|
|
3159
|
+
direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
|
|
3160
|
+
};
|
|
3161
|
+
readonly oracle: {
|
|
3162
|
+
direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
|
|
3163
|
+
};
|
|
3164
|
+
readonly postgres: {
|
|
3165
|
+
direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
|
|
3166
|
+
};
|
|
3167
|
+
readonly snowflake: {
|
|
3168
|
+
direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
|
|
3169
|
+
};
|
|
3170
|
+
};
|
|
3171
|
+
readonly set_datasource: (a: {
|
|
3172
|
+
value: Value;
|
|
3173
|
+
workspace_id?: Value;
|
|
3174
|
+
disabled?: boolean;
|
|
3175
|
+
description?: string;
|
|
3176
|
+
}) => Statement;
|
|
3177
|
+
};
|
|
3178
|
+
readonly ai: {
|
|
3179
|
+
readonly agent: {
|
|
3180
|
+
readonly run: typeof aiAgentRun;
|
|
3181
|
+
};
|
|
3182
|
+
readonly external: {
|
|
3183
|
+
mcp: {
|
|
3184
|
+
server_details: (a?: {
|
|
3185
|
+
as?: string;
|
|
3186
|
+
url?: Value;
|
|
3187
|
+
bearer_token?: Value;
|
|
3188
|
+
connection_type?: "sse" | "stream" | Value;
|
|
3189
|
+
disabled?: boolean;
|
|
3190
|
+
description?: string;
|
|
3191
|
+
asFilters?: FilterXdo[];
|
|
3192
|
+
}) => Statement;
|
|
3193
|
+
tool: {
|
|
3194
|
+
list: (a?: {
|
|
3195
|
+
as?: string;
|
|
3196
|
+
url?: Value;
|
|
3197
|
+
bearer_token?: Value;
|
|
3198
|
+
connection_type?: "sse" | "stream" | Value;
|
|
3199
|
+
disabled?: boolean;
|
|
3200
|
+
description?: string;
|
|
3201
|
+
asFilters?: FilterXdo[];
|
|
3202
|
+
}) => Statement;
|
|
3203
|
+
run: (a?: {
|
|
3204
|
+
as?: string;
|
|
3205
|
+
url?: Value;
|
|
3206
|
+
bearer_token?: Value;
|
|
3207
|
+
connection_type?: "sse" | "stream" | Value;
|
|
3208
|
+
tool?: Value;
|
|
3209
|
+
args?: Value;
|
|
3210
|
+
disabled?: boolean;
|
|
3211
|
+
description?: string;
|
|
3212
|
+
asFilters?: FilterXdo[];
|
|
3213
|
+
}) => Statement;
|
|
3214
|
+
};
|
|
3215
|
+
};
|
|
3216
|
+
};
|
|
3217
|
+
};
|
|
3218
|
+
readonly cloud: {
|
|
3219
|
+
readonly job: typeof cloudJob & {
|
|
3220
|
+
await: typeof cloudJobAwait;
|
|
3221
|
+
status: typeof cloudJobStatus;
|
|
3222
|
+
};
|
|
3223
|
+
readonly algolia: {
|
|
3224
|
+
request: (a: {
|
|
3225
|
+
as?: string;
|
|
3226
|
+
application_id: Value;
|
|
3227
|
+
api_key: Value;
|
|
3228
|
+
url: Value;
|
|
3229
|
+
method?: "POST" | "GET" | "DELETE" | "PUT" | Value;
|
|
3230
|
+
payload: Value;
|
|
3231
|
+
disabled?: boolean;
|
|
3232
|
+
description?: string;
|
|
3233
|
+
asFilters?: FilterXdo[];
|
|
3234
|
+
output?: OutputAuthored;
|
|
3235
|
+
}) => Statement;
|
|
3236
|
+
};
|
|
3237
|
+
readonly aws: {
|
|
3238
|
+
opensearch: {
|
|
3239
|
+
document: (a: {
|
|
3240
|
+
as?: string;
|
|
3241
|
+
auth_type?: "IAM" | "master" | Value;
|
|
3242
|
+
key_id?: Value;
|
|
3243
|
+
access_key?: Value;
|
|
3244
|
+
region?: Value;
|
|
3245
|
+
base_url: Value;
|
|
3246
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | Value;
|
|
3247
|
+
index?: Value;
|
|
3248
|
+
doc_id?: Value;
|
|
3249
|
+
doc?: Value;
|
|
3250
|
+
disabled?: boolean;
|
|
3251
|
+
description?: string;
|
|
3252
|
+
asFilters?: FilterXdo[];
|
|
3253
|
+
}) => Statement;
|
|
3254
|
+
query: (a?: {
|
|
3255
|
+
as?: string;
|
|
3256
|
+
auth_type?: "IAM" | "master" | Value;
|
|
3257
|
+
key_id?: Value;
|
|
3258
|
+
access_key?: Value;
|
|
3259
|
+
region?: Value;
|
|
3260
|
+
base_url?: Value;
|
|
3261
|
+
index?: Value;
|
|
3262
|
+
payload?: Value;
|
|
3263
|
+
size?: Value;
|
|
3264
|
+
from?: Value;
|
|
3265
|
+
included_fields?: Value;
|
|
3266
|
+
return_type?: "search" | "count" | Value;
|
|
3267
|
+
expression?: Value;
|
|
3268
|
+
sort?: Value;
|
|
3269
|
+
disabled?: boolean;
|
|
3270
|
+
description?: string;
|
|
3271
|
+
asFilters?: FilterXdo[];
|
|
3272
|
+
}) => Statement;
|
|
3273
|
+
request: (a?: {
|
|
3274
|
+
as?: string;
|
|
3275
|
+
auth_type?: "IAM" | "master" | Value;
|
|
3276
|
+
key_id?: Value;
|
|
3277
|
+
access_key?: Value;
|
|
3278
|
+
region?: Value;
|
|
3279
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH" | Value;
|
|
3280
|
+
url?: Value;
|
|
3281
|
+
query?: Value;
|
|
3282
|
+
disabled?: boolean;
|
|
3283
|
+
description?: string;
|
|
3284
|
+
asFilters?: FilterXdo[];
|
|
3285
|
+
}) => Statement;
|
|
3286
|
+
};
|
|
3287
|
+
s3: {
|
|
3288
|
+
delete_file: (a: {
|
|
3289
|
+
as?: string;
|
|
3290
|
+
bucket: Value;
|
|
3291
|
+
region: Value;
|
|
3292
|
+
key: Value;
|
|
3293
|
+
secret: Value;
|
|
3294
|
+
file_key: Value;
|
|
3295
|
+
disabled?: boolean;
|
|
3296
|
+
description?: string;
|
|
3297
|
+
asFilters?: FilterXdo[];
|
|
3298
|
+
}) => Statement;
|
|
3299
|
+
get_file_info: (a: {
|
|
3300
|
+
as?: string;
|
|
3301
|
+
bucket: Value;
|
|
3302
|
+
region: Value;
|
|
3303
|
+
key: Value;
|
|
3304
|
+
secret: Value;
|
|
3305
|
+
file_key: Value;
|
|
3306
|
+
disabled?: boolean;
|
|
3307
|
+
description?: string;
|
|
3308
|
+
asFilters?: FilterXdo[];
|
|
3309
|
+
}) => Statement;
|
|
3310
|
+
list_directory: (a: {
|
|
3311
|
+
as?: string;
|
|
3312
|
+
bucket: Value;
|
|
3313
|
+
region: Value;
|
|
3314
|
+
key: Value;
|
|
3315
|
+
secret: Value;
|
|
3316
|
+
prefix?: Value;
|
|
3317
|
+
next_page_token?: Value;
|
|
3318
|
+
disabled?: boolean;
|
|
3319
|
+
description?: string;
|
|
3320
|
+
asFilters?: FilterXdo[];
|
|
3321
|
+
}) => Statement;
|
|
3322
|
+
read_file: (a: {
|
|
3323
|
+
as?: string;
|
|
3324
|
+
bucket: Value;
|
|
3325
|
+
region: Value;
|
|
3326
|
+
key: Value;
|
|
3327
|
+
secret: Value;
|
|
3328
|
+
file_key: Value;
|
|
3329
|
+
disabled?: boolean;
|
|
3330
|
+
description?: string;
|
|
3331
|
+
asFilters?: FilterXdo[];
|
|
3332
|
+
}) => Statement;
|
|
3333
|
+
sign_url: (a: {
|
|
3334
|
+
as?: string;
|
|
3335
|
+
bucket: Value;
|
|
3336
|
+
region: Value;
|
|
3337
|
+
key: Value;
|
|
3338
|
+
secret: Value;
|
|
3339
|
+
file_key: Value;
|
|
3340
|
+
ttl?: Value;
|
|
3341
|
+
disabled?: boolean;
|
|
3342
|
+
description?: string;
|
|
3343
|
+
asFilters?: FilterXdo[];
|
|
3344
|
+
}) => Statement;
|
|
3345
|
+
upload_file: (a: {
|
|
3346
|
+
as?: string;
|
|
3347
|
+
bucket: Value;
|
|
3348
|
+
region: Value;
|
|
3349
|
+
key: Value;
|
|
3350
|
+
secret: Value;
|
|
3351
|
+
file_key?: Value;
|
|
3352
|
+
file: Value;
|
|
3353
|
+
metadata?: Value;
|
|
3354
|
+
object_lock_mode?: "compliance" | "governance" | Value;
|
|
3355
|
+
object_lock_retain_until?: Value;
|
|
3356
|
+
disabled?: boolean;
|
|
3357
|
+
description?: string;
|
|
3358
|
+
asFilters?: FilterXdo[];
|
|
3359
|
+
}) => Statement;
|
|
3360
|
+
};
|
|
3361
|
+
};
|
|
3362
|
+
readonly azure: {
|
|
3363
|
+
storage: {
|
|
3364
|
+
delete_file: (a: {
|
|
3365
|
+
as?: string;
|
|
3366
|
+
account_name: Value;
|
|
3367
|
+
account_key: Value;
|
|
3368
|
+
container_name: Value;
|
|
3369
|
+
filePath: Value;
|
|
3370
|
+
disabled?: boolean;
|
|
3371
|
+
description?: string;
|
|
3372
|
+
asFilters?: FilterXdo[];
|
|
3373
|
+
}) => Statement;
|
|
3374
|
+
get_file_info: (a: {
|
|
3375
|
+
as?: string;
|
|
3376
|
+
account_name: Value;
|
|
3377
|
+
account_key: Value;
|
|
3378
|
+
container_name: Value;
|
|
3379
|
+
filePath: Value;
|
|
3380
|
+
disabled?: boolean;
|
|
3381
|
+
description?: string;
|
|
3382
|
+
asFilters?: FilterXdo[];
|
|
3383
|
+
}) => Statement;
|
|
3384
|
+
list_directory: (a: {
|
|
3385
|
+
as?: string;
|
|
3386
|
+
account_name: Value;
|
|
3387
|
+
account_key: Value;
|
|
3388
|
+
container_name: Value;
|
|
3389
|
+
path?: Value;
|
|
3390
|
+
disabled?: boolean;
|
|
3391
|
+
description?: string;
|
|
3392
|
+
asFilters?: FilterXdo[];
|
|
3393
|
+
}) => Statement;
|
|
3394
|
+
read_file: (a: {
|
|
3395
|
+
as?: string;
|
|
3396
|
+
account_name: Value;
|
|
3397
|
+
account_key: Value;
|
|
3398
|
+
container_name: Value;
|
|
3399
|
+
filePath: Value;
|
|
3400
|
+
disabled?: boolean;
|
|
3401
|
+
description?: string;
|
|
3402
|
+
asFilters?: FilterXdo[];
|
|
3403
|
+
}) => Statement;
|
|
3404
|
+
sign_url: (a: {
|
|
3405
|
+
as?: string;
|
|
3406
|
+
account_name: Value;
|
|
3407
|
+
account_key: Value;
|
|
3408
|
+
container_name: Value;
|
|
3409
|
+
path: Value;
|
|
3410
|
+
ttl?: Value;
|
|
3411
|
+
disabled?: boolean;
|
|
3412
|
+
description?: string;
|
|
3413
|
+
asFilters?: FilterXdo[];
|
|
3414
|
+
}) => Statement;
|
|
3415
|
+
upload_file: (a: {
|
|
3416
|
+
as?: string;
|
|
3417
|
+
account_name: Value;
|
|
3418
|
+
account_key: Value;
|
|
3419
|
+
container_name: Value;
|
|
3420
|
+
filePath: Value;
|
|
3421
|
+
file: Value;
|
|
3422
|
+
metadata?: Value;
|
|
3423
|
+
disabled?: boolean;
|
|
3424
|
+
description?: string;
|
|
3425
|
+
asFilters?: FilterXdo[];
|
|
3426
|
+
}) => Statement;
|
|
3427
|
+
};
|
|
3428
|
+
};
|
|
3429
|
+
readonly elasticsearch: {
|
|
3430
|
+
document: (a: {
|
|
3431
|
+
as?: string;
|
|
3432
|
+
auth_type?: "Basic" | "Bearer" | "API Key" | Value;
|
|
3433
|
+
key_id: Value;
|
|
3434
|
+
access_key: Value;
|
|
3435
|
+
base_url: Value;
|
|
3436
|
+
index: Value;
|
|
3437
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | Value;
|
|
3438
|
+
doc_id: Value;
|
|
3439
|
+
doc: Value;
|
|
3440
|
+
disabled?: boolean;
|
|
3441
|
+
description?: string;
|
|
3442
|
+
asFilters?: FilterXdo[];
|
|
3443
|
+
}) => Statement;
|
|
3444
|
+
query: (a?: {
|
|
3445
|
+
as?: string;
|
|
3446
|
+
auth_type?: "Basic" | "Bearer" | "API Key" | Value;
|
|
3447
|
+
key_id?: Value;
|
|
3448
|
+
access_key?: Value;
|
|
3449
|
+
base_url?: Value;
|
|
3450
|
+
index?: Value;
|
|
3451
|
+
payload?: Value;
|
|
3452
|
+
size?: Value;
|
|
3453
|
+
from?: Value;
|
|
3454
|
+
included_fields?: Value;
|
|
3455
|
+
return_type?: "search" | "count" | Value;
|
|
3456
|
+
expression?: Value;
|
|
3457
|
+
sort?: Value;
|
|
3458
|
+
disabled?: boolean;
|
|
3459
|
+
description?: string;
|
|
3460
|
+
asFilters?: FilterXdo[];
|
|
3461
|
+
}) => Statement;
|
|
3462
|
+
request: (a?: {
|
|
3463
|
+
as?: string;
|
|
3464
|
+
auth_type?: "Basic" | "Bearer" | "API Key" | Value;
|
|
3465
|
+
key_id?: Value;
|
|
3466
|
+
access_key?: Value;
|
|
3467
|
+
method?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | Value;
|
|
3468
|
+
url?: Value;
|
|
3469
|
+
payload?: Value;
|
|
3470
|
+
disabled?: boolean;
|
|
3471
|
+
description?: string;
|
|
3472
|
+
asFilters?: FilterXdo[];
|
|
3473
|
+
}) => Statement;
|
|
3474
|
+
};
|
|
3475
|
+
readonly google: {
|
|
3476
|
+
storage: {
|
|
3477
|
+
delete_file: (a: {
|
|
3478
|
+
as?: string;
|
|
3479
|
+
service_account: Value;
|
|
3480
|
+
bucket: Value;
|
|
3481
|
+
filePath: Value;
|
|
3482
|
+
disabled?: boolean;
|
|
3483
|
+
description?: string;
|
|
3484
|
+
asFilters?: FilterXdo[];
|
|
3485
|
+
}) => Statement;
|
|
3486
|
+
get_file_info: (a: {
|
|
3487
|
+
as?: string;
|
|
3488
|
+
service_account: Value;
|
|
3489
|
+
bucket: Value;
|
|
3490
|
+
filePath: Value;
|
|
3491
|
+
disabled?: boolean;
|
|
3492
|
+
description?: string;
|
|
3493
|
+
asFilters?: FilterXdo[];
|
|
3494
|
+
}) => Statement;
|
|
3495
|
+
list_directory: (a: {
|
|
3496
|
+
as?: string;
|
|
3497
|
+
service_account: Value;
|
|
3498
|
+
bucket: Value;
|
|
3499
|
+
path: Value;
|
|
3500
|
+
disabled?: boolean;
|
|
3501
|
+
description?: string;
|
|
3502
|
+
asFilters?: FilterXdo[];
|
|
3503
|
+
}) => Statement;
|
|
3504
|
+
read_file: (a: {
|
|
3505
|
+
as?: string;
|
|
3506
|
+
service_account: Value;
|
|
3507
|
+
bucket: Value;
|
|
3508
|
+
filePath: Value;
|
|
3509
|
+
disabled?: boolean;
|
|
3510
|
+
description?: string;
|
|
3511
|
+
asFilters?: FilterXdo[];
|
|
3512
|
+
}) => Statement;
|
|
3513
|
+
sign_url: (a: {
|
|
3514
|
+
as?: string;
|
|
3515
|
+
service_account: Value;
|
|
3516
|
+
bucket: Value;
|
|
3517
|
+
filePath: Value;
|
|
3518
|
+
method?: "GET" | "POST" | Value;
|
|
3519
|
+
ttl?: Value;
|
|
3520
|
+
disabled?: boolean;
|
|
3521
|
+
description?: string;
|
|
3522
|
+
asFilters?: FilterXdo[];
|
|
3523
|
+
}) => Statement;
|
|
3524
|
+
upload_file: (a: {
|
|
3525
|
+
as?: string;
|
|
3526
|
+
service_account: Value;
|
|
3527
|
+
bucket: Value;
|
|
3528
|
+
filePath: Value;
|
|
3529
|
+
file: Value;
|
|
3530
|
+
metadata?: Value;
|
|
3531
|
+
disabled?: boolean;
|
|
3532
|
+
description?: string;
|
|
3533
|
+
asFilters?: FilterXdo[];
|
|
3534
|
+
}) => Statement;
|
|
3535
|
+
};
|
|
3536
|
+
};
|
|
3537
|
+
};
|
|
3538
|
+
readonly array: {
|
|
3539
|
+
readonly map: typeof arrayMap;
|
|
3540
|
+
readonly union: typeof arrayUnion;
|
|
3541
|
+
readonly difference: (a?: {
|
|
3542
|
+
as?: string;
|
|
3543
|
+
expr?: Value;
|
|
3544
|
+
value?: Value;
|
|
3545
|
+
by?: Value;
|
|
3546
|
+
disabled?: boolean;
|
|
3547
|
+
description?: string;
|
|
3548
|
+
asFilters?: FilterXdo[];
|
|
3549
|
+
}) => Statement;
|
|
3550
|
+
readonly every: (a?: {
|
|
3551
|
+
expr?: Value;
|
|
3552
|
+
as?: string;
|
|
3553
|
+
if?: Condition;
|
|
3554
|
+
disabled?: boolean;
|
|
3555
|
+
description?: string;
|
|
3556
|
+
asFilters?: FilterXdo[];
|
|
3557
|
+
output?: OutputAuthored;
|
|
3558
|
+
}) => Statement;
|
|
3559
|
+
readonly filter: (a?: {
|
|
3560
|
+
expr?: Value;
|
|
3561
|
+
as?: string;
|
|
3562
|
+
if?: Condition;
|
|
3563
|
+
disabled?: boolean;
|
|
3564
|
+
description?: string;
|
|
3565
|
+
asFilters?: FilterXdo[];
|
|
3566
|
+
}) => Statement;
|
|
3567
|
+
readonly filter_count: (a?: {
|
|
3568
|
+
expr?: Value;
|
|
3569
|
+
as?: string;
|
|
3570
|
+
if?: Condition;
|
|
3571
|
+
disabled?: boolean;
|
|
3572
|
+
description?: string;
|
|
3573
|
+
asFilters?: FilterXdo[];
|
|
3574
|
+
}) => Statement;
|
|
3575
|
+
readonly find: (a?: {
|
|
3576
|
+
expr?: Value;
|
|
3577
|
+
as?: string;
|
|
3578
|
+
if?: Condition;
|
|
3579
|
+
disabled?: boolean;
|
|
3580
|
+
description?: string;
|
|
3581
|
+
asFilters?: FilterXdo[];
|
|
3582
|
+
output?: OutputAuthored;
|
|
3583
|
+
}) => Statement;
|
|
3584
|
+
readonly find_index: (a?: {
|
|
3585
|
+
expr?: Value;
|
|
3586
|
+
as?: string;
|
|
3587
|
+
if?: Condition;
|
|
3588
|
+
disabled?: boolean;
|
|
3589
|
+
description?: string;
|
|
3590
|
+
asFilters?: FilterXdo[];
|
|
3591
|
+
}) => Statement;
|
|
3592
|
+
readonly group_by: (a?: {
|
|
3593
|
+
as?: string;
|
|
3594
|
+
expr?: Value;
|
|
3595
|
+
by?: Value;
|
|
3596
|
+
disabled?: boolean;
|
|
3597
|
+
description?: string;
|
|
3598
|
+
asFilters?: FilterXdo[];
|
|
3599
|
+
}) => Statement;
|
|
3600
|
+
readonly has: (a?: {
|
|
3601
|
+
expr?: Value;
|
|
3602
|
+
as?: string;
|
|
3603
|
+
if?: Condition;
|
|
3604
|
+
disabled?: boolean;
|
|
3605
|
+
description?: string;
|
|
3606
|
+
asFilters?: FilterXdo[];
|
|
3607
|
+
}) => Statement;
|
|
3608
|
+
readonly intersection: (a?: {
|
|
3609
|
+
as?: string;
|
|
3610
|
+
expr?: Value;
|
|
3611
|
+
value?: Value;
|
|
3612
|
+
by?: Value;
|
|
3613
|
+
disabled?: boolean;
|
|
3614
|
+
description?: string;
|
|
3615
|
+
asFilters?: FilterXdo[];
|
|
3616
|
+
}) => Statement;
|
|
3617
|
+
readonly merge: (a?: {
|
|
3618
|
+
name?: string;
|
|
3619
|
+
value?: Value;
|
|
3620
|
+
disabled?: boolean;
|
|
3621
|
+
description?: string;
|
|
3622
|
+
output?: OutputAuthored;
|
|
3623
|
+
}) => Statement;
|
|
3624
|
+
readonly partition: (a?: {
|
|
3625
|
+
expr?: Value;
|
|
3626
|
+
as?: string;
|
|
3627
|
+
if?: Condition;
|
|
3628
|
+
disabled?: boolean;
|
|
3629
|
+
description?: string;
|
|
3630
|
+
asFilters?: FilterXdo[];
|
|
3631
|
+
}) => Statement;
|
|
3632
|
+
readonly pop: (a?: {
|
|
3633
|
+
name?: string;
|
|
3634
|
+
as?: string;
|
|
3635
|
+
disabled?: boolean;
|
|
3636
|
+
description?: string;
|
|
3637
|
+
asFilters?: FilterXdo[];
|
|
3638
|
+
output?: OutputAuthored;
|
|
3639
|
+
}) => Statement;
|
|
3640
|
+
readonly push: (a: {
|
|
3641
|
+
name?: string;
|
|
3642
|
+
value: Value;
|
|
3643
|
+
disabled?: boolean;
|
|
3644
|
+
description?: string;
|
|
3645
|
+
output?: OutputAuthored;
|
|
3646
|
+
}) => Statement;
|
|
3647
|
+
readonly shift: (a?: {
|
|
3648
|
+
name?: string;
|
|
3649
|
+
as?: string;
|
|
3650
|
+
disabled?: boolean;
|
|
3651
|
+
description?: string;
|
|
3652
|
+
asFilters?: FilterXdo[];
|
|
3653
|
+
}) => Statement;
|
|
3654
|
+
readonly unshift: (a: {
|
|
3655
|
+
name?: string;
|
|
3656
|
+
value: Value;
|
|
3657
|
+
disabled?: boolean;
|
|
3658
|
+
description?: string;
|
|
3659
|
+
}) => Statement;
|
|
3660
|
+
};
|
|
3661
|
+
readonly expect: {
|
|
3662
|
+
readonly to_throw: typeof expectToThrow;
|
|
3663
|
+
readonly to_match: typeof expectToMatch;
|
|
3664
|
+
readonly to_be_defined: (a?: {
|
|
3665
|
+
expr?: Value;
|
|
3666
|
+
disabled?: boolean;
|
|
3667
|
+
description?: string;
|
|
3668
|
+
}) => Statement;
|
|
3669
|
+
readonly to_be_empty: (a?: {
|
|
3670
|
+
expr?: Value;
|
|
3671
|
+
disabled?: boolean;
|
|
3672
|
+
description?: string;
|
|
3673
|
+
}) => Statement;
|
|
3674
|
+
readonly to_be_false: (a?: {
|
|
3675
|
+
expr?: Value;
|
|
3676
|
+
disabled?: boolean;
|
|
3677
|
+
description?: string;
|
|
3678
|
+
}) => Statement;
|
|
3679
|
+
readonly to_be_greater_than: (a?: {
|
|
3680
|
+
expr?: Value;
|
|
3681
|
+
value?: Value;
|
|
3682
|
+
disabled?: boolean;
|
|
3683
|
+
description?: string;
|
|
3684
|
+
}) => Statement;
|
|
3685
|
+
readonly to_be_in_the_future: (a?: {
|
|
3686
|
+
expr?: Value;
|
|
3687
|
+
disabled?: boolean;
|
|
3688
|
+
description?: string;
|
|
3689
|
+
}) => Statement;
|
|
3690
|
+
readonly to_be_in_the_past: (a?: {
|
|
3691
|
+
expr?: Value;
|
|
3692
|
+
disabled?: boolean;
|
|
3693
|
+
description?: string;
|
|
3694
|
+
}) => Statement;
|
|
3695
|
+
readonly to_be_less_than: (a?: {
|
|
3696
|
+
expr?: Value;
|
|
3697
|
+
value?: Value;
|
|
3698
|
+
disabled?: boolean;
|
|
3699
|
+
description?: string;
|
|
3700
|
+
}) => Statement;
|
|
3701
|
+
readonly to_be_null: (a?: {
|
|
3702
|
+
expr?: Value;
|
|
3703
|
+
disabled?: boolean;
|
|
3704
|
+
description?: string;
|
|
3705
|
+
}) => Statement;
|
|
3706
|
+
readonly to_be_true: (a?: {
|
|
3707
|
+
expr?: Value;
|
|
3708
|
+
disabled?: boolean;
|
|
3709
|
+
description?: string;
|
|
3710
|
+
}) => Statement;
|
|
3711
|
+
readonly to_be_within: (a?: {
|
|
3712
|
+
expr?: Value;
|
|
3713
|
+
min?: Value;
|
|
3714
|
+
max?: Value;
|
|
3715
|
+
disabled?: boolean;
|
|
3716
|
+
description?: string;
|
|
3717
|
+
}) => Statement;
|
|
3718
|
+
readonly to_contain: (a?: {
|
|
3719
|
+
expr?: Value;
|
|
3720
|
+
value?: Value;
|
|
3721
|
+
disabled?: boolean;
|
|
3722
|
+
description?: string;
|
|
3723
|
+
}) => Statement;
|
|
3724
|
+
readonly to_end_with: (a?: {
|
|
3725
|
+
expr?: Value;
|
|
3726
|
+
value?: Value;
|
|
3727
|
+
disabled?: boolean;
|
|
3728
|
+
description?: string;
|
|
3729
|
+
}) => Statement;
|
|
3730
|
+
readonly to_equal: (a?: {
|
|
3731
|
+
expr?: Value;
|
|
3732
|
+
value?: Value;
|
|
3733
|
+
disabled?: boolean;
|
|
3734
|
+
description?: string;
|
|
3735
|
+
}) => Statement;
|
|
3736
|
+
readonly to_not_be_defined: (a?: {
|
|
3737
|
+
expr?: Value;
|
|
3738
|
+
disabled?: boolean;
|
|
3739
|
+
description?: string;
|
|
3740
|
+
}) => Statement;
|
|
3741
|
+
readonly to_not_be_null: (a?: {
|
|
3742
|
+
expr?: Value;
|
|
3743
|
+
disabled?: boolean;
|
|
3744
|
+
description?: string;
|
|
3745
|
+
}) => Statement;
|
|
3746
|
+
readonly to_not_equal: (a?: {
|
|
3747
|
+
expr?: Value;
|
|
3748
|
+
value?: Value;
|
|
3749
|
+
disabled?: boolean;
|
|
3750
|
+
description?: string;
|
|
3751
|
+
}) => Statement;
|
|
3752
|
+
readonly to_start_with: (a?: {
|
|
3753
|
+
expr?: Value;
|
|
3754
|
+
value?: Value;
|
|
3755
|
+
disabled?: boolean;
|
|
3756
|
+
description?: string;
|
|
3757
|
+
}) => Statement;
|
|
3758
|
+
};
|
|
3759
|
+
readonly security: {
|
|
3760
|
+
readonly create_auth_token: typeof createAuthToken;
|
|
3761
|
+
readonly create_guid: typeof createGuid;
|
|
3762
|
+
readonly check_password: (a?: {
|
|
3763
|
+
as?: string;
|
|
3764
|
+
text_password?: Value;
|
|
3765
|
+
hash_password?: Value;
|
|
3766
|
+
disabled?: boolean;
|
|
3767
|
+
description?: string;
|
|
3768
|
+
asFilters?: FilterXdo[];
|
|
3769
|
+
output?: OutputAuthored;
|
|
3770
|
+
}) => Statement;
|
|
3771
|
+
readonly create_curve_key: (a?: {
|
|
3772
|
+
as?: string;
|
|
3773
|
+
curve?: "P-256" | "P-384" | "P-521" | Value;
|
|
3774
|
+
format?: "object" | "base64" | Value;
|
|
3775
|
+
disabled?: boolean;
|
|
3776
|
+
description?: string;
|
|
3777
|
+
asFilters?: FilterXdo[];
|
|
3778
|
+
}) => Statement;
|
|
3779
|
+
readonly create_password: (a?: {
|
|
3780
|
+
as?: string;
|
|
3781
|
+
character_count?: Value;
|
|
3782
|
+
require_lowercase?: Value;
|
|
3783
|
+
require_uppercase?: Value;
|
|
3784
|
+
require_digit?: Value;
|
|
3785
|
+
require_symbol?: Value;
|
|
3786
|
+
symbol_whitelist?: Value;
|
|
3787
|
+
disabled?: boolean;
|
|
3788
|
+
description?: string;
|
|
3789
|
+
asFilters?: FilterXdo[];
|
|
3790
|
+
}) => Statement;
|
|
3791
|
+
readonly create_rsa_key: (a?: {
|
|
3792
|
+
as?: string;
|
|
3793
|
+
bits?: Value;
|
|
3794
|
+
format?: "object" | "base64" | Value;
|
|
3795
|
+
disabled?: boolean;
|
|
3796
|
+
description?: string;
|
|
3797
|
+
asFilters?: FilterXdo[];
|
|
3798
|
+
}) => Statement;
|
|
3799
|
+
readonly create_secret_key: (a?: {
|
|
3800
|
+
as?: string;
|
|
3801
|
+
bits?: Value;
|
|
3802
|
+
format?: "object" | "base64" | Value;
|
|
3803
|
+
disabled?: boolean;
|
|
3804
|
+
description?: string;
|
|
3805
|
+
asFilters?: FilterXdo[];
|
|
3806
|
+
}) => Statement;
|
|
3807
|
+
readonly create_uuid: (a?: {
|
|
3808
|
+
as?: string;
|
|
3809
|
+
disabled?: boolean;
|
|
3810
|
+
description?: string;
|
|
3811
|
+
asFilters?: FilterXdo[];
|
|
3812
|
+
}) => Statement;
|
|
3813
|
+
readonly decrypt: (a?: {
|
|
3814
|
+
as?: string;
|
|
3815
|
+
data?: Value;
|
|
3816
|
+
algorithm?: "aes-128-cbc" | "aes-192-cbc" | "aes-256-cbc" | "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm" | Value;
|
|
3817
|
+
key?: Value;
|
|
3818
|
+
iv?: Value;
|
|
3819
|
+
disabled?: boolean;
|
|
3820
|
+
description?: string;
|
|
3821
|
+
asFilters?: FilterXdo[];
|
|
3822
|
+
}) => Statement;
|
|
3823
|
+
readonly encrypt: (a?: {
|
|
3824
|
+
as?: string;
|
|
3825
|
+
data?: Value;
|
|
3826
|
+
algorithm?: "aes-128-cbc" | "aes-192-cbc" | "aes-256-cbc" | "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm" | Value;
|
|
3827
|
+
key?: Value;
|
|
3828
|
+
iv?: Value;
|
|
3829
|
+
disabled?: boolean;
|
|
3830
|
+
description?: string;
|
|
3831
|
+
asFilters?: FilterXdo[];
|
|
3832
|
+
}) => Statement;
|
|
3833
|
+
readonly jwe_decode: (a?: {
|
|
3834
|
+
as?: string;
|
|
3835
|
+
token?: Value;
|
|
3836
|
+
key?: Value;
|
|
3837
|
+
check_claims?: Value;
|
|
3838
|
+
key_algorithm?: "A128KW" | "A192KW" | "A256KW" | "A128GCMKW" | "A192GCMKW" | "A256GCMKW" | "ECDH-ES+A128KW" | "ECDH-ES+A192KW" | "ECDH-ES+A256KW" | Value;
|
|
3839
|
+
content_algorithm?: "A128GCM" | "A192GCM" | "A256GCM" | "A128CBC-HS256" | "A192CBC-HS384" | "A256CBC-HS512" | Value;
|
|
3840
|
+
timeDrift?: Value;
|
|
3841
|
+
disabled?: boolean;
|
|
3842
|
+
description?: string;
|
|
3843
|
+
asFilters?: FilterXdo[];
|
|
3844
|
+
}) => Statement;
|
|
3845
|
+
readonly jwe_encode: (a?: {
|
|
3846
|
+
as?: string;
|
|
3847
|
+
headers?: Value;
|
|
3848
|
+
claims?: Value;
|
|
3849
|
+
key?: Value;
|
|
3850
|
+
key_algorithm?: "A128KW" | "A192KW" | "A256KW" | "A128GCMKW" | "A192GCMKW" | "A256GCMKW" | "ECDH-ES+A128KW" | "ECDH-ES+A192KW" | "ECDH-ES+A256KW" | Value;
|
|
3851
|
+
content_algorithm?: "A128GCM" | "A192GCM" | "A256GCM" | "A128CBC-HS256" | "A192CBC-HS384" | "A256CBC-HS512" | Value;
|
|
3852
|
+
ttl?: Value;
|
|
3853
|
+
disabled?: boolean;
|
|
3854
|
+
description?: string;
|
|
3855
|
+
asFilters?: FilterXdo[];
|
|
3856
|
+
}) => Statement;
|
|
3857
|
+
readonly jws_decode: (a?: {
|
|
3858
|
+
as?: string;
|
|
3859
|
+
token?: Value;
|
|
3860
|
+
key?: Value;
|
|
3861
|
+
check_claims?: Value;
|
|
3862
|
+
signature_algorithm?: "PS256" | "PS384" | "PS512" | "RS256" | "RS384" | "RS512" | "HS256" | "HS384" | "HS512" | "ES256" | "ES384" | "ES512" | Value;
|
|
3863
|
+
timeDrift?: Value;
|
|
3864
|
+
disabled?: boolean;
|
|
3865
|
+
description?: string;
|
|
3866
|
+
asFilters?: FilterXdo[];
|
|
3867
|
+
}) => Statement;
|
|
3868
|
+
readonly jws_encode: (a?: {
|
|
3869
|
+
as?: string;
|
|
3870
|
+
headers?: Value;
|
|
3871
|
+
claims?: Value;
|
|
3872
|
+
key?: Value;
|
|
3873
|
+
signature_algorithm?: "PS256" | "PS384" | "PS512" | "RS256" | "RS384" | "RS512" | "HS256" | "HS384" | "HS512" | "ES256" | "ES384" | "ES512" | Value;
|
|
3874
|
+
ttl?: Value;
|
|
3875
|
+
disabled?: boolean;
|
|
3876
|
+
description?: string;
|
|
3877
|
+
asFilters?: FilterXdo[];
|
|
3878
|
+
}) => Statement;
|
|
3879
|
+
readonly random_bytes: (a?: {
|
|
3880
|
+
as?: string;
|
|
3881
|
+
length?: Value;
|
|
3882
|
+
disabled?: boolean;
|
|
3883
|
+
description?: string;
|
|
3884
|
+
asFilters?: FilterXdo[];
|
|
3885
|
+
}) => Statement;
|
|
3886
|
+
readonly random_number: (a?: {
|
|
3887
|
+
as?: string;
|
|
3888
|
+
min?: Value;
|
|
3889
|
+
max?: Value;
|
|
3890
|
+
disabled?: boolean;
|
|
3891
|
+
description?: string;
|
|
3892
|
+
asFilters?: FilterXdo[];
|
|
3893
|
+
}) => Statement;
|
|
3894
|
+
};
|
|
3895
|
+
readonly util: {
|
|
3896
|
+
readonly get_raw_input: typeof getRawInput;
|
|
3897
|
+
readonly get_input: typeof getRawInput;
|
|
3898
|
+
readonly post_process: typeof postProcess;
|
|
3899
|
+
readonly ip_lookup: typeof ipLookup;
|
|
3900
|
+
readonly set_header: typeof setHeader;
|
|
3901
|
+
readonly geo_distance: (a?: {
|
|
3902
|
+
as?: string;
|
|
3903
|
+
latitude_1?: Value;
|
|
3904
|
+
longitude_1?: Value;
|
|
3905
|
+
latitude_2?: Value;
|
|
3906
|
+
longitude_2?: Value;
|
|
3907
|
+
disabled?: boolean;
|
|
3908
|
+
description?: string;
|
|
3909
|
+
asFilters?: FilterXdo[];
|
|
3910
|
+
}) => Statement;
|
|
3911
|
+
readonly get_all_input: (a?: {
|
|
3912
|
+
as?: string;
|
|
3913
|
+
disabled?: boolean;
|
|
3914
|
+
description?: string;
|
|
3915
|
+
asFilters?: FilterXdo[];
|
|
3916
|
+
}) => Statement;
|
|
3917
|
+
readonly get_env: (a?: {
|
|
3918
|
+
as?: string;
|
|
3919
|
+
disabled?: boolean;
|
|
3920
|
+
description?: string;
|
|
3921
|
+
asFilters?: FilterXdo[];
|
|
3922
|
+
}) => Statement;
|
|
3923
|
+
readonly get_vars: (a?: {
|
|
3924
|
+
as?: string;
|
|
3925
|
+
disabled?: boolean;
|
|
3926
|
+
description?: string;
|
|
3927
|
+
asFilters?: FilterXdo[];
|
|
3928
|
+
}) => Statement;
|
|
3929
|
+
readonly send_email: (a?: {
|
|
3930
|
+
as?: string;
|
|
3931
|
+
service_provider?: "resend" | "xano" | Value;
|
|
3932
|
+
api_key?: Value;
|
|
3933
|
+
subject?: Value;
|
|
3934
|
+
message?: Value;
|
|
3935
|
+
to?: Value;
|
|
3936
|
+
bcc?: Value;
|
|
3937
|
+
cc?: Value;
|
|
3938
|
+
from?: Value;
|
|
3939
|
+
reply_to?: Value;
|
|
3940
|
+
scheduled_at?: Value;
|
|
3941
|
+
disabled?: boolean;
|
|
3942
|
+
description?: string;
|
|
3943
|
+
asFilters?: FilterXdo[];
|
|
3944
|
+
}) => Statement;
|
|
3945
|
+
readonly sleep: (a: {
|
|
3946
|
+
value: Value;
|
|
3947
|
+
disabled?: boolean;
|
|
3948
|
+
description?: string;
|
|
3949
|
+
}) => Statement;
|
|
3950
|
+
readonly template_engine: (a: {
|
|
3951
|
+
as?: string;
|
|
3952
|
+
value: Value;
|
|
3953
|
+
disabled?: boolean;
|
|
3954
|
+
description?: string;
|
|
3955
|
+
asFilters?: FilterXdo[];
|
|
3956
|
+
}) => Statement;
|
|
3957
|
+
};
|
|
3958
|
+
readonly storage: {
|
|
3959
|
+
readonly create_attachment: typeof createAttachment;
|
|
3960
|
+
readonly create_audio: typeof createAudio;
|
|
3961
|
+
readonly create_image: typeof createImage;
|
|
3962
|
+
readonly create_video: typeof createVideo;
|
|
3963
|
+
readonly create_file_resource: (a: {
|
|
3964
|
+
as?: string;
|
|
3965
|
+
filename: Value;
|
|
3966
|
+
filedata: Value;
|
|
3967
|
+
disabled?: boolean;
|
|
3968
|
+
description?: string;
|
|
3969
|
+
asFilters?: FilterXdo[];
|
|
3970
|
+
output?: OutputAuthored;
|
|
3971
|
+
}) => Statement;
|
|
3972
|
+
readonly delete_file: (a: {
|
|
3973
|
+
pathname: Value;
|
|
3974
|
+
disabled?: boolean;
|
|
3975
|
+
description?: string;
|
|
3976
|
+
output?: OutputAuthored;
|
|
3977
|
+
}) => Statement;
|
|
3978
|
+
readonly read_file_resource: (a: {
|
|
3979
|
+
as?: string;
|
|
3980
|
+
value: Value;
|
|
3981
|
+
disabled?: boolean;
|
|
3982
|
+
description?: string;
|
|
3983
|
+
asFilters?: FilterXdo[];
|
|
3984
|
+
}) => Statement;
|
|
3985
|
+
readonly sign_private_url: (a: {
|
|
3986
|
+
as?: string;
|
|
3987
|
+
pathname: Value;
|
|
3988
|
+
ttl?: Value;
|
|
3989
|
+
disabled?: boolean;
|
|
3990
|
+
description?: string;
|
|
3991
|
+
asFilters?: FilterXdo[];
|
|
3992
|
+
}) => Statement;
|
|
3993
|
+
};
|
|
3994
|
+
readonly await: (a?: {
|
|
3995
|
+
as?: string;
|
|
3996
|
+
ids?: Value;
|
|
3997
|
+
timeout?: Value;
|
|
3998
|
+
disabled?: boolean;
|
|
3999
|
+
description?: string;
|
|
4000
|
+
asFilters?: FilterXdo[];
|
|
4001
|
+
}) => Statement;
|
|
4002
|
+
readonly datadog: {
|
|
4003
|
+
log: (a?: {
|
|
4004
|
+
message?: Value;
|
|
4005
|
+
status?: "debug" | "info" | "notice" | "warn" | "error" | "critical" | "alert" | "emergency" | Value;
|
|
4006
|
+
attributes?: Value;
|
|
4007
|
+
service?: Value;
|
|
4008
|
+
source?: Value;
|
|
4009
|
+
env?: Value;
|
|
4010
|
+
hostname?: Value;
|
|
4011
|
+
tags?: Value;
|
|
4012
|
+
timestamp?: Value;
|
|
4013
|
+
connection?: Value;
|
|
4014
|
+
disabled?: boolean;
|
|
4015
|
+
description?: string;
|
|
4016
|
+
}) => Statement;
|
|
4017
|
+
log_bulk: (a: {
|
|
4018
|
+
entries: Value;
|
|
4019
|
+
connection?: Value;
|
|
4020
|
+
disabled?: boolean;
|
|
4021
|
+
description?: string;
|
|
4022
|
+
}) => Statement;
|
|
4023
|
+
metric: (a: {
|
|
4024
|
+
metric?: Value;
|
|
4025
|
+
value: Value;
|
|
4026
|
+
type?: "count" | "gauge" | "rate" | "histogram" | "distribution" | Value;
|
|
4027
|
+
tags?: Value;
|
|
4028
|
+
service?: Value;
|
|
4029
|
+
source?: Value;
|
|
4030
|
+
env?: Value;
|
|
4031
|
+
hostname?: Value;
|
|
4032
|
+
timestamp?: Value;
|
|
4033
|
+
connection?: Value;
|
|
4034
|
+
disabled?: boolean;
|
|
4035
|
+
description?: string;
|
|
4036
|
+
}) => Statement;
|
|
4037
|
+
metric_bulk: (a: {
|
|
4038
|
+
entries: Value;
|
|
4039
|
+
connection?: Value;
|
|
4040
|
+
disabled?: boolean;
|
|
4041
|
+
description?: string;
|
|
4042
|
+
}) => Statement;
|
|
4043
|
+
};
|
|
4044
|
+
readonly debug: {
|
|
4045
|
+
log: (a: {
|
|
4046
|
+
value: Value;
|
|
4047
|
+
disabled?: boolean;
|
|
4048
|
+
description?: string;
|
|
4049
|
+
}) => Statement;
|
|
4050
|
+
stop: (a: {
|
|
4051
|
+
value: Value;
|
|
4052
|
+
disabled?: boolean;
|
|
4053
|
+
description?: string;
|
|
4054
|
+
}) => Statement;
|
|
4055
|
+
};
|
|
4056
|
+
readonly math: {
|
|
4057
|
+
add: (a: {
|
|
4058
|
+
name?: string;
|
|
4059
|
+
value: Value;
|
|
4060
|
+
disabled?: boolean;
|
|
4061
|
+
description?: string;
|
|
4062
|
+
output?: OutputAuthored;
|
|
4063
|
+
}) => Statement;
|
|
4064
|
+
bitwise: {
|
|
4065
|
+
and: (a: {
|
|
4066
|
+
name?: string;
|
|
4067
|
+
value: Value;
|
|
4068
|
+
disabled?: boolean;
|
|
4069
|
+
description?: string;
|
|
4070
|
+
output?: OutputAuthored;
|
|
4071
|
+
}) => Statement;
|
|
4072
|
+
or: (a: {
|
|
4073
|
+
name?: string;
|
|
4074
|
+
value: Value;
|
|
4075
|
+
disabled?: boolean;
|
|
4076
|
+
description?: string;
|
|
4077
|
+
output?: OutputAuthored;
|
|
4078
|
+
}) => Statement;
|
|
4079
|
+
xor: (a: {
|
|
4080
|
+
name?: string;
|
|
4081
|
+
value: Value;
|
|
4082
|
+
disabled?: boolean;
|
|
4083
|
+
description?: string;
|
|
4084
|
+
output?: OutputAuthored;
|
|
4085
|
+
}) => Statement;
|
|
4086
|
+
};
|
|
4087
|
+
div: (a: {
|
|
4088
|
+
name?: string;
|
|
4089
|
+
value: Value;
|
|
4090
|
+
disabled?: boolean;
|
|
4091
|
+
description?: string;
|
|
4092
|
+
}) => Statement;
|
|
4093
|
+
mod: (a: {
|
|
4094
|
+
name?: string;
|
|
4095
|
+
value: Value;
|
|
4096
|
+
disabled?: boolean;
|
|
4097
|
+
description?: string;
|
|
4098
|
+
}) => Statement;
|
|
4099
|
+
mul: (a: {
|
|
4100
|
+
name?: string;
|
|
4101
|
+
value: Value;
|
|
4102
|
+
disabled?: boolean;
|
|
4103
|
+
description?: string;
|
|
4104
|
+
}) => Statement;
|
|
4105
|
+
sub: (a: {
|
|
4106
|
+
name?: string;
|
|
4107
|
+
value: Value;
|
|
4108
|
+
disabled?: boolean;
|
|
4109
|
+
description?: string;
|
|
4110
|
+
}) => Statement;
|
|
4111
|
+
};
|
|
4112
|
+
readonly object: {
|
|
4113
|
+
entries: (a?: {
|
|
4114
|
+
as?: string;
|
|
4115
|
+
value?: Value;
|
|
4116
|
+
disabled?: boolean;
|
|
4117
|
+
description?: string;
|
|
4118
|
+
asFilters?: FilterXdo[];
|
|
4119
|
+
output?: OutputAuthored;
|
|
4120
|
+
}) => Statement;
|
|
4121
|
+
keys: (a?: {
|
|
4122
|
+
as?: string;
|
|
4123
|
+
value?: Value;
|
|
4124
|
+
disabled?: boolean;
|
|
4125
|
+
description?: string;
|
|
4126
|
+
asFilters?: FilterXdo[];
|
|
4127
|
+
output?: OutputAuthored;
|
|
4128
|
+
}) => Statement;
|
|
4129
|
+
values: (a?: {
|
|
4130
|
+
as?: string;
|
|
4131
|
+
value?: Value;
|
|
4132
|
+
disabled?: boolean;
|
|
4133
|
+
description?: string;
|
|
4134
|
+
asFilters?: FilterXdo[];
|
|
4135
|
+
output?: OutputAuthored;
|
|
4136
|
+
}) => Statement;
|
|
4137
|
+
};
|
|
4138
|
+
readonly redis: {
|
|
4139
|
+
count: (a: {
|
|
4140
|
+
as?: string;
|
|
4141
|
+
key: Value;
|
|
4142
|
+
disabled?: boolean;
|
|
4143
|
+
description?: string;
|
|
4144
|
+
asFilters?: FilterXdo[];
|
|
4145
|
+
}) => Statement;
|
|
4146
|
+
decr: (a: {
|
|
4147
|
+
as?: string;
|
|
4148
|
+
key: Value;
|
|
4149
|
+
by?: Value;
|
|
4150
|
+
disabled?: boolean;
|
|
4151
|
+
description?: string;
|
|
4152
|
+
asFilters?: FilterXdo[];
|
|
4153
|
+
}) => Statement;
|
|
4154
|
+
del: (a: {
|
|
4155
|
+
key: Value;
|
|
4156
|
+
disabled?: boolean;
|
|
4157
|
+
description?: string;
|
|
4158
|
+
}) => Statement;
|
|
4159
|
+
get: (a: {
|
|
4160
|
+
as?: string;
|
|
4161
|
+
key: Value;
|
|
4162
|
+
disabled?: boolean;
|
|
4163
|
+
description?: string;
|
|
4164
|
+
asFilters?: FilterXdo[];
|
|
4165
|
+
}) => Statement;
|
|
4166
|
+
has: (a: {
|
|
4167
|
+
as?: string;
|
|
4168
|
+
key: Value;
|
|
4169
|
+
disabled?: boolean;
|
|
4170
|
+
description?: string;
|
|
4171
|
+
asFilters?: FilterXdo[];
|
|
4172
|
+
}) => Statement;
|
|
4173
|
+
incr: (a: {
|
|
4174
|
+
as?: string;
|
|
4175
|
+
key: Value;
|
|
4176
|
+
by?: Value;
|
|
4177
|
+
disabled?: boolean;
|
|
4178
|
+
description?: string;
|
|
4179
|
+
asFilters?: FilterXdo[];
|
|
4180
|
+
}) => Statement;
|
|
4181
|
+
keys: (a: {
|
|
4182
|
+
as?: string;
|
|
4183
|
+
search: Value;
|
|
4184
|
+
disabled?: boolean;
|
|
4185
|
+
description?: string;
|
|
4186
|
+
asFilters?: FilterXdo[];
|
|
4187
|
+
}) => Statement;
|
|
4188
|
+
pop: (a: {
|
|
4189
|
+
as?: string;
|
|
4190
|
+
key: Value;
|
|
4191
|
+
count?: Value;
|
|
4192
|
+
disabled?: boolean;
|
|
4193
|
+
description?: string;
|
|
4194
|
+
asFilters?: FilterXdo[];
|
|
4195
|
+
}) => Statement;
|
|
4196
|
+
push: (a: {
|
|
4197
|
+
as?: string;
|
|
4198
|
+
key: Value;
|
|
4199
|
+
value: Value;
|
|
4200
|
+
disabled?: boolean;
|
|
4201
|
+
description?: string;
|
|
4202
|
+
asFilters?: FilterXdo[];
|
|
4203
|
+
}) => Statement;
|
|
4204
|
+
range: (a: {
|
|
4205
|
+
as?: string;
|
|
4206
|
+
key: Value;
|
|
4207
|
+
start?: Value;
|
|
4208
|
+
stop?: Value;
|
|
4209
|
+
disabled?: boolean;
|
|
4210
|
+
description?: string;
|
|
4211
|
+
asFilters?: FilterXdo[];
|
|
4212
|
+
}) => Statement;
|
|
4213
|
+
ratelimit: (a: {
|
|
4214
|
+
as?: string;
|
|
4215
|
+
key: Value;
|
|
4216
|
+
max?: Value;
|
|
4217
|
+
ttl?: Value;
|
|
4218
|
+
error?: Value;
|
|
4219
|
+
disabled?: boolean;
|
|
4220
|
+
description?: string;
|
|
4221
|
+
asFilters?: FilterXdo[];
|
|
4222
|
+
}) => Statement;
|
|
4223
|
+
remove: (a: {
|
|
4224
|
+
as?: string;
|
|
4225
|
+
key: Value;
|
|
4226
|
+
value: Value;
|
|
4227
|
+
count?: Value;
|
|
4228
|
+
disabled?: boolean;
|
|
4229
|
+
description?: string;
|
|
4230
|
+
asFilters?: FilterXdo[];
|
|
4231
|
+
}) => Statement;
|
|
4232
|
+
set: (a: {
|
|
4233
|
+
as?: string;
|
|
4234
|
+
key: Value;
|
|
4235
|
+
data: Value;
|
|
4236
|
+
ttl?: Value;
|
|
4237
|
+
create_only?: Value;
|
|
4238
|
+
disabled?: boolean;
|
|
4239
|
+
description?: string;
|
|
4240
|
+
asFilters?: FilterXdo[];
|
|
4241
|
+
}) => Statement;
|
|
4242
|
+
shift: (a: {
|
|
4243
|
+
as?: string;
|
|
4244
|
+
key: Value;
|
|
4245
|
+
count?: Value;
|
|
4246
|
+
disabled?: boolean;
|
|
4247
|
+
description?: string;
|
|
4248
|
+
asFilters?: FilterXdo[];
|
|
4249
|
+
}) => Statement;
|
|
4250
|
+
unshift: (a: {
|
|
4251
|
+
as?: string;
|
|
4252
|
+
key: Value;
|
|
4253
|
+
value: Value;
|
|
4254
|
+
disabled?: boolean;
|
|
4255
|
+
description?: string;
|
|
4256
|
+
asFilters?: FilterXdo[];
|
|
4257
|
+
}) => Statement;
|
|
4258
|
+
};
|
|
4259
|
+
readonly text: {
|
|
4260
|
+
append: (a: {
|
|
4261
|
+
name?: string;
|
|
4262
|
+
value: Value;
|
|
4263
|
+
disabled?: boolean;
|
|
4264
|
+
description?: string;
|
|
4265
|
+
}) => Statement;
|
|
4266
|
+
contains: (a: {
|
|
4267
|
+
name?: string;
|
|
4268
|
+
as?: string;
|
|
4269
|
+
value: Value;
|
|
4270
|
+
disabled?: boolean;
|
|
4271
|
+
description?: string;
|
|
4272
|
+
asFilters?: FilterXdo[];
|
|
4273
|
+
}) => Statement;
|
|
4274
|
+
ends_with: (a: {
|
|
4275
|
+
name?: string;
|
|
4276
|
+
as?: string;
|
|
4277
|
+
value: Value;
|
|
4278
|
+
disabled?: boolean;
|
|
4279
|
+
description?: string;
|
|
4280
|
+
asFilters?: FilterXdo[];
|
|
4281
|
+
}) => Statement;
|
|
4282
|
+
icontains: (a: {
|
|
4283
|
+
name?: string;
|
|
4284
|
+
as?: string;
|
|
4285
|
+
value: Value;
|
|
4286
|
+
disabled?: boolean;
|
|
4287
|
+
description?: string;
|
|
4288
|
+
asFilters?: FilterXdo[];
|
|
4289
|
+
}) => Statement;
|
|
4290
|
+
iends_with: (a: {
|
|
4291
|
+
name?: string;
|
|
4292
|
+
as?: string;
|
|
4293
|
+
value: Value;
|
|
4294
|
+
disabled?: boolean;
|
|
4295
|
+
description?: string;
|
|
4296
|
+
asFilters?: FilterXdo[];
|
|
4297
|
+
}) => Statement;
|
|
4298
|
+
istarts_with: (a: {
|
|
4299
|
+
name?: string;
|
|
4300
|
+
as?: string;
|
|
4301
|
+
value: Value;
|
|
4302
|
+
disabled?: boolean;
|
|
4303
|
+
description?: string;
|
|
4304
|
+
asFilters?: FilterXdo[];
|
|
4305
|
+
}) => Statement;
|
|
4306
|
+
ltrim: (a: {
|
|
4307
|
+
name?: string;
|
|
4308
|
+
value: Value;
|
|
4309
|
+
disabled?: boolean;
|
|
4310
|
+
description?: string;
|
|
4311
|
+
}) => Statement;
|
|
4312
|
+
prepend: (a: {
|
|
4313
|
+
name?: string;
|
|
4314
|
+
value: Value;
|
|
4315
|
+
disabled?: boolean;
|
|
4316
|
+
description?: string;
|
|
4317
|
+
}) => Statement;
|
|
4318
|
+
rtrim: (a: {
|
|
4319
|
+
name?: string;
|
|
4320
|
+
value: Value;
|
|
4321
|
+
disabled?: boolean;
|
|
4322
|
+
description?: string;
|
|
4323
|
+
}) => Statement;
|
|
4324
|
+
starts_with: (a: {
|
|
4325
|
+
name?: string;
|
|
4326
|
+
as?: string;
|
|
4327
|
+
value: Value;
|
|
4328
|
+
disabled?: boolean;
|
|
4329
|
+
description?: string;
|
|
4330
|
+
asFilters?: FilterXdo[];
|
|
4331
|
+
}) => Statement;
|
|
4332
|
+
trim: (a: {
|
|
4333
|
+
name?: string;
|
|
4334
|
+
value: Value;
|
|
4335
|
+
disabled?: boolean;
|
|
4336
|
+
description?: string;
|
|
4337
|
+
}) => Statement;
|
|
4338
|
+
};
|
|
4339
|
+
readonly zip: {
|
|
4340
|
+
add_to_archive: (a: {
|
|
4341
|
+
file: Value;
|
|
4342
|
+
filename: Value;
|
|
4343
|
+
zip: Value;
|
|
4344
|
+
password?: Value;
|
|
4345
|
+
password_encryption?: Value;
|
|
4346
|
+
disabled?: boolean;
|
|
4347
|
+
description?: string;
|
|
4348
|
+
}) => Statement;
|
|
4349
|
+
create_archive: (a: {
|
|
4350
|
+
as?: string;
|
|
4351
|
+
filename: Value;
|
|
4352
|
+
password?: Value;
|
|
4353
|
+
password_encryption?: "standard" | "AES-128" | "AES-192" | "AES-256" | Value;
|
|
4354
|
+
disabled?: boolean;
|
|
4355
|
+
description?: string;
|
|
4356
|
+
asFilters?: FilterXdo[];
|
|
4357
|
+
}) => Statement;
|
|
4358
|
+
delete_from_archive: (a: {
|
|
4359
|
+
filename: Value;
|
|
4360
|
+
zip: Value;
|
|
4361
|
+
password?: Value;
|
|
4362
|
+
disabled?: boolean;
|
|
4363
|
+
description?: string;
|
|
4364
|
+
}) => Statement;
|
|
4365
|
+
extract: (a: {
|
|
4366
|
+
as?: string;
|
|
4367
|
+
zip: Value;
|
|
4368
|
+
password?: Value;
|
|
4369
|
+
disabled?: boolean;
|
|
4370
|
+
description?: string;
|
|
4371
|
+
asFilters?: FilterXdo[];
|
|
4372
|
+
}) => Statement;
|
|
4373
|
+
view_contents: (a: {
|
|
4374
|
+
as?: string;
|
|
4375
|
+
zip: Value;
|
|
4376
|
+
password?: Value;
|
|
4377
|
+
disabled?: boolean;
|
|
4378
|
+
description?: string;
|
|
4379
|
+
asFilters?: FilterXdo[];
|
|
4380
|
+
}) => Statement;
|
|
4381
|
+
};
|
|
4382
|
+
};
|
|
4383
|
+
|
|
4384
|
+
/**
|
|
4385
|
+
* Wide aliases for the def types that carry generics — the annotation that lets
|
|
4386
|
+
* a workspace be assembled out of independently-authored modules (issue #71).
|
|
4387
|
+
*
|
|
4388
|
+
* The problem is TypeScript's, not the SDK's. `register*` stores defs and does
|
|
4389
|
+
* not read their brands, so it takes them however they arrive. What fails is the
|
|
4390
|
+
* expression that BUILDS the array:
|
|
4391
|
+
*
|
|
4392
|
+
* ```ts
|
|
4393
|
+
* const modules = [catalogModule, chatModule];
|
|
4394
|
+
* workspace("app").registerTables(modules.flatMap((m) => m.tables)); // ✗ TS2322
|
|
4395
|
+
* ```
|
|
4396
|
+
*
|
|
4397
|
+
* `Array.prototype.flatMap` is declared `(cb: (…) => U | ReadonlyArray<U>)`, so
|
|
4398
|
+
* `U` binds to the FIRST element's table type and every later table is checked
|
|
4399
|
+
* against that one table's schema. The diagnostic is ~40 lines of expanded
|
|
4400
|
+
* generics ending in a comparison between two unrelated column names, and it
|
|
4401
|
+
* names neither `flatMap` nor the real cause. `.concat()` collapses the same way.
|
|
4402
|
+
*
|
|
4403
|
+
* Two spellings work. Annotate the module array with the wide alias:
|
|
4404
|
+
*
|
|
4405
|
+
* ```ts
|
|
4406
|
+
* const modules: { tables: readonly AnyTableDef[] }[] = [catalogModule, chatModule];
|
|
4407
|
+
* workspace("app").registerTables(modules.flatMap((m) => [...m.tables])); // ✓
|
|
4408
|
+
* ```
|
|
4409
|
+
*
|
|
4410
|
+
* …or skip the loop and let an array LITERAL infer the union across every
|
|
4411
|
+
* element at once, which is the documented form:
|
|
4412
|
+
*
|
|
4413
|
+
* ```ts
|
|
4414
|
+
* workspace("app").registerTables([...catalogModule.tables, ...chatModule.tables]); // ✓
|
|
4415
|
+
* ```
|
|
4416
|
+
*
|
|
4417
|
+
* Nothing is lost by widening here. The typing an author actually needs lives on
|
|
4418
|
+
* the `table()`/`query()` handle they hold and pass to `s.db.*` — it is never
|
|
4419
|
+
* read back off the registered array.
|
|
4420
|
+
*
|
|
4421
|
+
* Aliases exist for exactly the def types whose generics can collapse this way.
|
|
4422
|
+
* `ApiGroupDef`, `TaskDef`, `TriggerDef`, `MiddlewareDef` and the rest carry no
|
|
4423
|
+
* generics, so a heterogeneous array of them infers cleanly with no annotation.
|
|
4424
|
+
*/
|
|
4425
|
+
|
|
4426
|
+
/** Any `table()` handle, whatever its schema — see the module note on `flatMap`. */
|
|
4427
|
+
type AnyTableDef = TableDef;
|
|
4428
|
+
/** Any `query()` handle, whatever its input, stack, response, or name. */
|
|
4429
|
+
type AnyQueryDef = QueryHandle;
|
|
4430
|
+
/** Any `defineFunction()` def, whatever its input, stack, or response. */
|
|
4431
|
+
type AnyFunctionDef = FunctionDef;
|
|
4432
|
+
/** Any `addon()` handle, whatever it grafts onto the row. */
|
|
4433
|
+
type AnyAddonDef = AddonDef;
|
|
4434
|
+
|
|
4435
|
+
/**
|
|
4436
|
+
* `compile()` — façade over the `function` object kind (KTD-2). The envelope
|
|
4437
|
+
* encoding now lives in `src/kinds/function.ts`; this keeps the MVP's public
|
|
4438
|
+
* `compile`/`encodeResponse` surface stable.
|
|
4439
|
+
*/
|
|
4440
|
+
|
|
4441
|
+
/** Compile a `FunctionDef` into the flattened importable function `xdo`. */
|
|
4442
|
+
declare function compile(fn: FunctionDef): FunctionXdo;
|
|
4443
|
+
|
|
4444
|
+
/**
|
|
4445
|
+
* An input binding the engine SKIPS.
|
|
4446
|
+
*
|
|
4447
|
+
* A statement's `input[]` entry carries an `ignore` flag. When it is set the
|
|
4448
|
+
* engine records `"<name>:ignore"` and never binds the value at all, so the
|
|
4449
|
+
* parameter falls back to its declared default — which is NOT the same as
|
|
4450
|
+
* passing an empty value, and not the same as omitting the entry (the entry,
|
|
4451
|
+
* with its remembered value, is still stored).
|
|
4452
|
+
*
|
|
4453
|
+
* 1,766 real input entries carry it. The db row-write family already models it
|
|
4454
|
+
* as an `ignore` flag on a `data:` cell; this is the same state for the
|
|
4455
|
+
* spec-routed statements, whose fields are plain {@link Value}s with nowhere to
|
|
4456
|
+
* hang a flag.
|
|
4457
|
+
*
|
|
4458
|
+
* It applies to EVERY spec-routed statement, not only the handful whose stored
|
|
4459
|
+
* envelope spells the entry members out in full — the lean and full input forms
|
|
4460
|
+
* are two serializations of one entry model (issue #16).
|
|
4461
|
+
*
|
|
4462
|
+
* The marker is carried on a non-enumerable property, so it never reaches
|
|
4463
|
+
* `JSON.stringify` and an ignored value serializes exactly like the value it
|
|
4464
|
+
* wraps — the flag is read only by the input encoder, which moves it onto the
|
|
4465
|
+
* entry.
|
|
4466
|
+
*/
|
|
4467
|
+
|
|
4468
|
+
/**
|
|
4469
|
+
* Mark an input binding as ignored — stored with its value, skipped at runtime.
|
|
4470
|
+
*
|
|
4471
|
+
* Recovery-oriented: `codegen` emits it for a stored `ignore: true` entry so a
|
|
4472
|
+
* pulled workspace reproduces its bytes. Authoring one by hand is legal and
|
|
4473
|
+
* means "keep this parameter's value on record, but do not send it".
|
|
4474
|
+
*/
|
|
4475
|
+
declare function ignored(value: Value): Value;
|
|
4476
|
+
|
|
4477
|
+
export { type ActionCallArgs, type AddonCallArgs, AddonDef, type AddonSpec, type AgentRunResult, type AiAgentRunArgs, type AnyAddonDef, type AnyFunctionDef, type AnyQueryDef, type AnyTableDef, type ApiCallArgs, type ApplyFilter, type ApplyFilters, type ArrayMapArgs, type CloudJobArgs, type CloudJobAwaitArgs, type CloudJobStatusArgs, type CreateAuthTokenArgs, type DbAddArgs, type DbAddOrEditArgs, type DbAggregate, type DbAggregatePaging, type DbBind, type DbBulkAddArgs, type DbBulkDeleteArgs, type DbBulkWriteArgs, type DbDelArgs, type DbDirectQueryArgs, type DbDistinct, type DbEditArgs, DbEval, type DbExternal, type DbExternalPermissions, type DbExternalQueryArgs, type DbField, type DbGetArgs, type DbHasArgs, type DbJoin, type DbPaging, type DbPatchArgs, type DbQueryArgs, type DbResponseType, type DbReturnType, type DbSchemaArgs, type DbTransactionArgs, type DbTruncateArgs, DbWhere, type ExpectToThrowArgs, type ExternalSqlEngine, FilterXdo, FilteredValue, type ForArgs, type ForeachArgs, FromFieldMap, type FunctionCallArgs, FunctionDef, type FunctionRunArgs, FunctionXdo, type GetRawInputArgs, type HeaderMap, type HttpMethod, type InferInput, type InferResponse, InferRow, type IpLookupArgs, type IpLookupResult, MicroserviceDef, type MiddlewareCallArgs, ObjInput, ObjValue, ObjectRef, QueryHandle, type RealtimeEventArgs, RefValue, SortDirective, type StackTupleWidened, Statement, StatementAnnotations, StatementOptions, type SwitchArgs, type SwitchCaseArgs, TableDef, type TaskCallArgs, type ToolCallArgs, type TriggerCallArgs, type TryCatchArgs, Value, type WhileArgs, type WorkflowTestCallArgs, XanoFileRef, actionCall, actionPackageCall, addonCall, aiAgentRun, apiCall, arrayMap, arrayUnion, cloudJob, cloudJobAwait, cloudJobStatus, comment, compile, conditional, createAuthToken, dbAdd, dbAddOrEdit, dbBulkAdd, dbBulkDelete, dbBulkPatch, dbBulkUpdate, dbDel, dbDirectQuery, dbEdit, dbExternalQuery, dbGet, dbHas, dbPatch, dbQuery, dbSchema, dbTransaction, dbTruncate, debugLog, die, expectToThrow, fileUrl, forLoop, foreachBreak, foreachContinue, foreachLoop, foreachRemove, functionCall, functionRun, getRawInput, group, ignored, ipLookup, middlewareCall, postProcess, realtimeEvent, returnValue, s, setVar, switchCase, switchStatement, taskCall, toolCall, triggerCall, tryCatch, updateVar, whileLoop, workflowTestCall };
|