@relyio/sdk 0.19.0 → 0.21.0
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/CHANGELOG.md +16 -0
- package/dist/automations/index.cjs +1 -1
- package/dist/automations/index.d.cts +2 -1588
- package/dist/automations/index.d.ts +2 -1588
- package/dist/automations/index.js +1 -1
- package/dist/{chunk-ZO6QDYJG.cjs → chunk-5WGMIQBH.cjs} +2 -2
- package/dist/{chunk-W2A4OTCI.js → chunk-EQUZNVAR.js} +2 -2
- package/dist/{chunk-P23G5NXD.cjs → chunk-K66MBRI4.cjs} +68 -51
- package/dist/{chunk-356SF5Y2.js → chunk-L42C4G2S.js} +25 -8
- package/dist/{chunk-T7LGREB3.js → chunk-OUR7OUUZ.js} +3 -3
- package/dist/{chunk-NN45CSPZ.cjs → chunk-UO2QRYKV.cjs} +3 -3
- package/dist/client/index.cjs +5 -5
- package/dist/client/index.d.cts +4 -4
- package/dist/client/index.d.ts +4 -4
- package/dist/client/index.js +3 -3
- package/dist/{define-content-type-BZ6X8GvL.d.cts → define-content-type-C2HnCYYX.d.cts} +1 -1
- package/dist/{define-content-type-C12jh8cY.d.ts → define-content-type-CVLUusfx.d.ts} +1 -1
- package/dist/dev-handshake/index.cjs +8 -8
- package/dist/dev-handshake/index.d.cts +1 -1
- package/dist/dev-handshake/index.d.ts +1 -1
- package/dist/dev-handshake/index.js +1 -1
- package/dist/extensions/index.cjs +3 -3
- package/dist/extensions/index.d.cts +2 -4
- package/dist/extensions/index.d.ts +2 -4
- package/dist/extensions/index.js +1 -1
- package/dist/functions/index.cjs +1 -1
- package/dist/functions/index.d.cts +2 -4
- package/dist/functions/index.d.ts +2 -4
- package/dist/functions/index.js +1 -1
- package/dist/{index-BxNnlc5D.d.ts → index-BAdue7TR.d.ts} +54 -9
- package/dist/{index-D5jyIeQ5.d.cts → index-BNf3S9W9.d.cts} +54 -9
- package/dist/{index-C-MymZTe.d.ts → index-BY1xU93u.d.ts} +1 -1
- package/dist/{index-DN0l8RHw.d.cts → index-Cmup6HJY.d.cts} +1 -1
- package/dist/index-D0r6fnvl.d.ts +2304 -0
- package/dist/index-U5NbHg3N.d.cts +2304 -0
- package/dist/index.cjs +76 -76
- package/dist/index.d.cts +7 -8
- package/dist/index.d.ts +7 -8
- package/dist/index.js +4 -4
- package/dist/preview/index.cjs +3 -3
- package/dist/preview/index.js +1 -1
- package/dist/rich-text/index.d.cts +2 -2
- package/dist/rich-text/index.d.ts +2 -2
- package/dist/schema/index.cjs +1 -1
- package/dist/schema/index.d.cts +947 -4
- package/dist/schema/index.d.ts +947 -4
- package/dist/schema/index.js +1 -1
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +5 -5
- package/dist/define-schema-BPlZl4a2.d.cts +0 -947
- package/dist/define-schema-CK7TtYot.d.ts +0 -947
- package/dist/register-BiMQKVp-.d.ts +0 -693
- package/dist/register-DeMsaurp.d.cts +0 -693
|
@@ -1,947 +0,0 @@
|
|
|
1
|
-
import { cK as ConditionTree, aS as FieldMember, A as AIConfig, an as FieldValues, ao as DeclaredFields, cR as components, cy as RecordFile, cx as FileUpload, r as KeyedMembers, cS as DisplayFieldOf, s as KeyedMembersOf, aV as ContentTypeDefinition, a$ as SingletonContentTypeDefinition, b4 as SettingsGroupDefinition, aL as LocaleDefinition, bP as RoleDefinition, c6 as WorkflowDefinition, co as ViewDefinition, b9 as AssetTypeDefinition, aX as InferContentType, bS as KeyedRoles, cr as KeyedViews, cT as CheckedLocales, cU as CheckedRoles, cV as CheckedWorkflow, cW as CheckedSection, cX as KeysDeclared, cY as ContributedRecordType, cZ as LocaleCodesOf, c_ as StagesDeclared, bT as KeyedRolesAsList, cs as KeyedViewsAsList } from './define-content-type-BZ6X8GvL.cjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A Record type's End-user Policies (spec 4, REL-3883, ADR 0027): what the End users of a
|
|
5
|
-
* customer's app — and anonymous visitors — may do with the type's Records, action by action.
|
|
6
|
-
*
|
|
7
|
-
* A rule is one of three names or a condition:
|
|
8
|
-
*
|
|
9
|
-
* - `'owner'` — the End user the Record's Owner field names, and no one else. The type must declare
|
|
10
|
-
* an Owner field (`fields.owner()`), and a visitor with no token is never one.
|
|
11
|
-
* - `'signedIn'` — any End user, whoever owns the Record; never a visitor.
|
|
12
|
-
* - `'anyone'` — every End user and every visitor.
|
|
13
|
-
* - a condition tree (`@relyio/schema/lists`) over three roots: `record.*` — the Record's own
|
|
14
|
-
* fields, compiled against the stored Records — and the two the asker supplies, `owner` (the End
|
|
15
|
-
* user's subject, absent for a visitor, so `owner.exists()` is "signed in") and `claims.*` (what
|
|
16
|
-
* their token claims). A condition holds of anyone it admits, a visitor included.
|
|
17
|
-
*
|
|
18
|
-
* An action with no rule gives End users and visitors nothing of the type: a type that declares no
|
|
19
|
-
* `endUsers` is closed to them, so adding a Record type never exposes it by accident. A write
|
|
20
|
-
* (`create`, `update`, `delete`) is a rule too, or for `create` and `update` `{ when, fields }`:
|
|
21
|
-
* who may, and which fields they may set (REL-3885 declares the shape and its deploy refusals,
|
|
22
|
-
* {@link endUserPolicyFaults}; REL-3884 enforces it). Every backend reads the declaration through the
|
|
23
|
-
* `endUserPolicies` projection, never from here.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/** The rules a Policy may name rather than spell as a condition. */
|
|
27
|
-
declare const NAMED_POLICY_RULES: readonly ['owner', 'signedIn', 'anyone'];
|
|
28
|
-
type NamedPolicyRule = (typeof NAMED_POLICY_RULES)[number];
|
|
29
|
-
/** One action's rule: a name, or a condition over the Record and the asker. */
|
|
30
|
-
type PolicyRule = NamedPolicyRule | ConditionTree;
|
|
31
|
-
/** A write rule naming the fields an End user may set: who may (`when`), and which (`fields`). */
|
|
32
|
-
interface FieldsWriteRule {
|
|
33
|
-
readonly when: PolicyRule;
|
|
34
|
-
readonly fields: readonly string[];
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* A `create` or `update` rule: a rule alone — the End users it admits set any field an End user may
|
|
38
|
-
* set — or `{ when, fields }`, naming the fields.
|
|
39
|
-
*/
|
|
40
|
-
type WriteRule = PolicyRule | FieldsWriteRule;
|
|
41
|
-
/**
|
|
42
|
-
* What a Record type does with an End user's Records when the identity source reports them deleted
|
|
43
|
-
* (spec 4): `keep` them, or `delete` them through the pipeline. Only a type with an owner field.
|
|
44
|
-
*/
|
|
45
|
-
declare const OWNER_DELETED_ACTIONS: readonly ['keep', 'delete'];
|
|
46
|
-
type OwnerDeletedAction = (typeof OWNER_DELETED_ACTIONS)[number];
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Record type definition matching @relyio/schema RecordTypeSchema (spec 1, ADR 0023)
|
|
50
|
-
*
|
|
51
|
-
* A Record is the data an app writes while it runs — an order, a stock level, a review, a cart —
|
|
52
|
-
* declared in the schema beside the content types and deployed with them. It is live the moment it
|
|
53
|
-
* is written: no drafts, no publication, no locales, no version history. So a Record type is a
|
|
54
|
-
* content type's shape without the editorial half: no `workflow`, no `hierarchical`, and its fields
|
|
55
|
-
* take every kind but `slug` and are never `localized` (deploy refuses both:
|
|
56
|
-
* `RECORD_TYPE_SLUG_FIELD`, `RECORD_TYPE_LOCALIZED_FIELD`).
|
|
57
|
-
*
|
|
58
|
-
* A Record type's references point outward: at content types, asset types and other Record types.
|
|
59
|
-
* An entry never references a Record — a content type whose reference names a Record type fails to
|
|
60
|
-
* compile under `defineSchema`, and deploy refuses it (`REFERENCE_TO_RECORD_TYPE`).
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* A Record type's configuration in the keyed form (REL-1969), as a content type's: its key under
|
|
65
|
-
* `defineSchema({ recordTypes })` is its id — one namespace with every content, singleton, settings
|
|
66
|
-
* group and asset type id — and `fields` a record keyed by Field id. `displayName` is derived from
|
|
67
|
-
* the key when left out.
|
|
68
|
-
*/
|
|
69
|
-
interface KeyedRecordTypeConfig<R extends KeyedMembers = KeyedMembers> {
|
|
70
|
-
/** Display name shown in the UI. Derived from the type's key when left out: `orderLine` → "Order line" */
|
|
71
|
-
displayName?: string;
|
|
72
|
-
/** Plural display name shown in the UI (e.g., "Orders" for "Order"); not derived */
|
|
73
|
-
displayNamePlural?: string;
|
|
74
|
-
/** Description of the Record type */
|
|
75
|
-
description?: string;
|
|
76
|
-
/** AI configuration: guidance for agents reading these Records */
|
|
77
|
-
ai?: AIConfig;
|
|
78
|
-
/** Access tags for role-based access control */
|
|
79
|
-
accessTags?: string[];
|
|
80
|
-
/** The Field a Record's title is in lists and references: one of this type's own (REL-2416) */
|
|
81
|
-
displayField?: DisplayFieldOf<R>;
|
|
82
|
-
/**
|
|
83
|
-
* Sets of this type's own Fields no two Records hold the same values of in one Dataset (REL-3782):
|
|
84
|
-
* `[['product', 'author']]` keeps one review per product per author. One Field alone says it with
|
|
85
|
-
* `unique: true` in its own config. A Record writing values another holds is refused, naming the
|
|
86
|
-
* set and the Record holding them.
|
|
87
|
-
*/
|
|
88
|
-
unique?: ReadonlyArray<ReadonlyArray<DisplayFieldOf<R>>>;
|
|
89
|
-
/**
|
|
90
|
-
* How long each Record lives after its last write, in whole hours or days — `'36h'`, `'7d'`
|
|
91
|
-
* (REL-3775). Every write moves the deadline on, so an active Record never expires; past it, the
|
|
92
|
-
* Record is deleted as a delete would delete it. Left out, a Record lives until it is deleted.
|
|
93
|
-
*/
|
|
94
|
-
expireAfter?: RecordExpiry;
|
|
95
|
-
/**
|
|
96
|
-
* What the End users of your app — and anonymous visitors with your publishable key — may do with
|
|
97
|
-
* this type's Records (spec 4, REL-3883). Left out, they read nothing of it: your server reads
|
|
98
|
-
* every Record with a secret key, as it always did.
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* endUsers: { read: 'owner' } // each End user lists and gets only the Records they own
|
|
102
|
-
* endUsers: { read: conditionRoot('record').status.eq('visible') } // anyone, visible ones only
|
|
103
|
-
* endUsers: { update: { when: 'owner', fields: ['note'] } } // an owner changes the note alone
|
|
104
|
-
*/
|
|
105
|
-
endUsers?: RecordTypeEndUsers<DisplayFieldOf<R>>;
|
|
106
|
-
/**
|
|
107
|
-
* What becomes of an End user's Records when your identity source reports them deleted — Clerk's
|
|
108
|
-
* `user.deleted` (spec 4): `'keep'` them, or `'delete'` them. Only a type with `fields.owner()`.
|
|
109
|
-
*/
|
|
110
|
-
onOwnerDeleted?: OwnerDeletedAction;
|
|
111
|
-
/** Each Field under its id, in the order the form shows them */
|
|
112
|
-
fields: R;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* A Record type's End-user Policies (spec 4, REL-3883), action by action. A rule is `'owner'` — the
|
|
116
|
-
* End user the type's `fields.owner()` names; `'signedIn'` — any End user; `'anyone'` — every End
|
|
117
|
-
* user and visitor; or a condition over `record.*` (the Record's fields), `owner` (the End user's
|
|
118
|
-
* subject, absent for a visitor) and `claims.*` (what their token claims), built with
|
|
119
|
-
* `conditionRoot`, `and`, `or` and `not`.
|
|
120
|
-
*/
|
|
121
|
-
interface RecordTypeEndUsers<F extends string = string> {
|
|
122
|
-
/** Who may list, count, facet and get the Records. Left out, End users and visitors may not. */
|
|
123
|
-
readonly read?: PolicyRule;
|
|
124
|
-
/**
|
|
125
|
-
* Who may create a Record — a rule, or `{ when, fields }` naming the fields they may set, each one
|
|
126
|
-
* of this type's own. Never `'anyone'`, and never an owner, sequence, counter or Private field in
|
|
127
|
-
* `fields`. Left out, End users create none. RelyIO sets the owner from the End user's token.
|
|
128
|
-
*/
|
|
129
|
-
readonly create?: RecordWriteRule<F>;
|
|
130
|
-
/** Who may update a Record, asked of it as stored, as `create`. Left out, End users update none. */
|
|
131
|
-
readonly update?: RecordWriteRule<F>;
|
|
132
|
-
/** Who may delete a Record, asked of it as stored. Never `'anyone'`. Left out, none. */
|
|
133
|
-
readonly delete?: PolicyRule;
|
|
134
|
-
/**
|
|
135
|
-
* How many writes a minute one End user makes to the type (REL-3884): 60 when left out. Over it,
|
|
136
|
-
* a write is refused `RATE_LIMIT_EXCEEDED` with `Retry-After`, before anything is written.
|
|
137
|
-
*/
|
|
138
|
-
readonly perUser?: {
|
|
139
|
-
readonly writesPerMinute: number;
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* A `create` or `update` rule whose `fields` name this type's own Fields (REL-3884): the schema's
|
|
144
|
-
* `WriteRule`, checked as you type.
|
|
145
|
-
*/
|
|
146
|
-
type RecordWriteRule<F extends string = string> = PolicyRule | {
|
|
147
|
-
readonly when: PolicyRule;
|
|
148
|
-
readonly fields: readonly F[];
|
|
149
|
-
};
|
|
150
|
-
/** A whole number of hours or days: `'36h'`, `'7d'`. Deploy refuses any other form. */
|
|
151
|
-
type RecordExpiry = `${number}h` | `${number}d`;
|
|
152
|
-
/**
|
|
153
|
-
* Record type definition - preserves field types for inference
|
|
154
|
-
*/
|
|
155
|
-
interface RecordTypeDefinition<TFields extends readonly FieldMember[] = readonly FieldMember[]> {
|
|
156
|
-
readonly _tag: 'recordType';
|
|
157
|
-
/** Absent until `defineSchema` writes the type's key here; deploy takes the key either way. */
|
|
158
|
-
readonly name?: string;
|
|
159
|
-
/** Absent in the keyed form until `defineSchema` derives it from the type's key */
|
|
160
|
-
readonly displayName?: string;
|
|
161
|
-
readonly displayNamePlural?: string;
|
|
162
|
-
readonly description?: string;
|
|
163
|
-
/** AI configuration: guidance for agents reading these Records */
|
|
164
|
-
readonly ai?: AIConfig;
|
|
165
|
-
/** Field ID to use as a Record's display title */
|
|
166
|
-
readonly displayField?: string;
|
|
167
|
-
readonly accessTags?: string[];
|
|
168
|
-
/** Sets of Fields no two Records hold the same values of in one Dataset (REL-3782) */
|
|
169
|
-
readonly unique?: string[][];
|
|
170
|
-
/** How long each Record lives after its last write (REL-3775) */
|
|
171
|
-
readonly expireAfter?: RecordExpiry;
|
|
172
|
-
/** What End users and visitors may do with the Records (REL-3883) */
|
|
173
|
-
readonly endUsers?: RecordTypeEndUsers;
|
|
174
|
-
/** What becomes of an End user's Records when they are deleted (spec 4) */
|
|
175
|
-
readonly onOwnerDeleted?: OwnerDeletedAction;
|
|
176
|
-
readonly fields: TFields;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Define a Record type: the shape of the data an app writes while it runs.
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* export const inventory = defineRecordType({
|
|
183
|
-
* fields: {
|
|
184
|
-
* product: fields.reference({ required: true, to: 'product' }),
|
|
185
|
-
* stock: fields.integer({ required: true, min: 0 }),
|
|
186
|
-
* },
|
|
187
|
-
* })
|
|
188
|
-
* // Under its key in defineSchema: recordTypes: { inventory }
|
|
189
|
-
*/
|
|
190
|
-
declare function defineRecordType<R extends KeyedMembers>(config: KeyedRecordTypeConfig<R>): RecordTypeDefinition<readonly KeyedMembersOf<R>[]>;
|
|
191
|
-
/**
|
|
192
|
-
* Type alias for any Record type definition.
|
|
193
|
-
*/
|
|
194
|
-
type AnyRecordTypeDefinition = RecordTypeDefinition<any>;
|
|
195
|
-
/**
|
|
196
|
-
* A Record's values as its Record type declares them (REL-3771): a required field always present,
|
|
197
|
-
* every other one optional, each typed as a read returns it. What `records(type).create` takes.
|
|
198
|
-
*/
|
|
199
|
-
type RecordFieldsOf<T extends AnyRecordTypeDefinition> = FieldValues<DeclaredFields<T>>;
|
|
200
|
-
/**
|
|
201
|
-
* A Record's values as a write takes them (REL-3781, REL-3824): {@link RecordFieldsOf} without its
|
|
202
|
-
* Sequences, which RelyIO numbers and a create or an update that sets one is refused — and a File
|
|
203
|
-
* as the upload holding its bytes (`FileUpload`), never the address only a read answers. What
|
|
204
|
-
* `records(type).create` and `update` take.
|
|
205
|
-
*/
|
|
206
|
-
type RecordWriteFieldsOf<T extends AnyRecordTypeDefinition> = {
|
|
207
|
-
[K in keyof Omit<RecordFieldsOf<T>, SequenceIdsOf<T>>]: WrittenAs<RecordFieldsOf<T>[K]>;
|
|
208
|
-
};
|
|
209
|
-
/**
|
|
210
|
-
* A Record's values as an update takes them (REL-3774, REL-3765): {@link RecordWriteFieldsOf}
|
|
211
|
-
* without its Counters — a create starts one, and after that it moves only by `increment` and
|
|
212
|
-
* `decrement`, applied in the write itself; a value an update set would overwrite a move made since
|
|
213
|
-
* the read, and the server refuses it (`COUNTER_USE_INCREMENT_OR_DECREMENT`). What
|
|
214
|
-
* `records(type).update` takes.
|
|
215
|
-
*/
|
|
216
|
-
type RecordUpdateFieldsOf<T extends AnyRecordTypeDefinition> = Omit<RecordWriteFieldsOf<T>, CounterIdsOf<T>>;
|
|
217
|
-
/** The ids of a Record type's Counter fields. */
|
|
218
|
-
type CounterIdsOf<T extends AnyRecordTypeDefinition> = Extract<DeclaredFields<T>, {
|
|
219
|
-
readonly type: 'counter';
|
|
220
|
-
}>['id'];
|
|
221
|
-
/** A value as a write sends it: a File as its upload, every other value as a read answers it. */
|
|
222
|
-
type WrittenAs<V> = V extends RecordFile ? FileUpload : V;
|
|
223
|
-
/** The ids of a Record type's Sequence fields. */
|
|
224
|
-
type SequenceIdsOf<T extends AnyRecordTypeDefinition> = Extract<DeclaredFields<T>, {
|
|
225
|
-
readonly type: 'sequence';
|
|
226
|
-
}>['id'];
|
|
227
|
-
/**
|
|
228
|
-
* A Record as a read answers it: its fields, and `_metadata` — the document's `RecordMetadata`, no
|
|
229
|
-
* locale, publication or version (REL-3771).
|
|
230
|
-
*
|
|
231
|
-
* @example
|
|
232
|
-
* type Order = InferRecordType<typeof order>
|
|
233
|
-
* // { shopperEmail: string; total: number; …; _metadata: RecordMetadata }
|
|
234
|
-
*/
|
|
235
|
-
type InferRecordType<T extends AnyRecordTypeDefinition> = RecordFieldsOf<T> & {
|
|
236
|
-
_metadata: components['schemas']['RecordMetadata'];
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Query definition matching @relyio/schema QueryDefinitionSchema
|
|
241
|
-
*
|
|
242
|
-
* Queries define predefined API endpoints with filtering, sorting, and caching.
|
|
243
|
-
*
|
|
244
|
-
* This is a hand-written mirror: `@relyio/sdk` is published standalone and does not depend on
|
|
245
|
-
* `@relyio/schema`, so a field added there has to be added here too. When the two drifted, `limit`
|
|
246
|
-
* was the casualty — the documentation writes `limit: '${limit?20}'` and this file said `number` —
|
|
247
|
-
* and so were `fullText` and `type`, which a query pulled by `relyio generate-types` carried and
|
|
248
|
-
* this refused. `@relyio/codegen-typescript`'s `src/__tests__/sdk-definition-config.types.ts` now
|
|
249
|
-
* fails to compile when a key, whether it is required, or the values it accepts differs from the
|
|
250
|
-
* schema's, block by block (REL-1457).
|
|
251
|
-
*/
|
|
252
|
-
/** One value a query clause compares with. */
|
|
253
|
-
type QueryScalar = string | number | boolean;
|
|
254
|
-
/**
|
|
255
|
-
* A window back or forward from the moment of the read — `{ amount: 7, unit: 'days' }` — which
|
|
256
|
-
* `$inTheLast` and `$inTheNext` take, as a list's `where` takes them.
|
|
257
|
-
*/
|
|
258
|
-
type QueryRelativeWindow = {
|
|
259
|
-
amount: number;
|
|
260
|
-
unit: 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'years';
|
|
261
|
-
};
|
|
262
|
-
/**
|
|
263
|
-
* The operators `where` and `filters` compare a field with — `{ price: { $gte: 10 } }` — the
|
|
264
|
-
* `$`-prefixed operators a list's `where` takes, meaning what they mean there (REL-2439).
|
|
265
|
-
*
|
|
266
|
-
* The service's one vocabulary for `where`, `filters` and `having`, which deploy refuses any other
|
|
267
|
-
* key against (REL-1479). The bare form (`{ price: { gte: 10 } }`) is gone: deploy refuses it,
|
|
268
|
-
* saying what to write. A value may be a parameter expression: a list operator takes a list or a
|
|
269
|
-
* parameter that supplies one, a flag a boolean or a parameter. A parameter only ever fills a value;
|
|
270
|
-
* which operators a condition asks is written here, never supplied.
|
|
271
|
-
* `@relyio/codegen-typescript`'s `sdk-definition-config.types.ts` fails to compile when an operator,
|
|
272
|
-
* or what it takes, differs from the schema's.
|
|
273
|
-
*/
|
|
274
|
-
type WhereOperator = {
|
|
275
|
-
/** Equal to */
|
|
276
|
-
$eq?: QueryScalar;
|
|
277
|
-
/** Not equal to */
|
|
278
|
-
$ne?: QueryScalar;
|
|
279
|
-
/** Greater than */
|
|
280
|
-
$gt?: QueryScalar;
|
|
281
|
-
/** Greater than or equal to */
|
|
282
|
-
$gte?: QueryScalar;
|
|
283
|
-
/** Less than */
|
|
284
|
-
$lt?: QueryScalar;
|
|
285
|
-
/** Less than or equal to */
|
|
286
|
-
$lte?: QueryScalar;
|
|
287
|
-
/** One of the values given */
|
|
288
|
-
$in?: QueryScalar[] | string;
|
|
289
|
-
/** None of the values given */
|
|
290
|
-
$nin?: QueryScalar[] | string;
|
|
291
|
-
/** Contains the text, ignoring case */
|
|
292
|
-
$contains?: QueryScalar;
|
|
293
|
-
/** Starts with the text, matching case */
|
|
294
|
-
$startsWith?: QueryScalar;
|
|
295
|
-
/** Ends with the text, matching case */
|
|
296
|
-
$endsWith?: QueryScalar;
|
|
297
|
-
/** The field holds a value (true) or does not (false) */
|
|
298
|
-
$exists?: boolean | string;
|
|
299
|
-
/** The value is empty (true) or not (false) */
|
|
300
|
-
$isNull?: boolean | string;
|
|
301
|
-
/** A date within the span back from the moment of the read */
|
|
302
|
-
$inTheLast?: QueryRelativeWindow;
|
|
303
|
-
/** A date within the span forward from the moment of the read */
|
|
304
|
-
$inTheNext?: QueryRelativeWindow;
|
|
305
|
-
};
|
|
306
|
-
/**
|
|
307
|
-
* The operators `having` compares a metric with: the same as `where`'s, each with a literal, since
|
|
308
|
-
* `having` reads the values the aggregate computed and substitutes no parameter. A metric holds no
|
|
309
|
-
* date of an entry's, so neither relative window is taken.
|
|
310
|
-
*/
|
|
311
|
-
type HavingOperator = {
|
|
312
|
-
$eq?: QueryScalar;
|
|
313
|
-
$ne?: QueryScalar;
|
|
314
|
-
$gt?: QueryScalar;
|
|
315
|
-
$gte?: QueryScalar;
|
|
316
|
-
$lt?: QueryScalar;
|
|
317
|
-
$lte?: QueryScalar;
|
|
318
|
-
$in?: QueryScalar[];
|
|
319
|
-
$nin?: QueryScalar[];
|
|
320
|
-
$contains?: QueryScalar;
|
|
321
|
-
$startsWith?: QueryScalar;
|
|
322
|
-
$endsWith?: QueryScalar;
|
|
323
|
-
$exists?: boolean;
|
|
324
|
-
$isNull?: boolean;
|
|
325
|
-
$inTheLast?: never;
|
|
326
|
-
$inTheNext?: never;
|
|
327
|
-
};
|
|
328
|
-
type WhereValue = string | number | boolean | (string | number | boolean)[] | WhereOperator;
|
|
329
|
-
type WhereCondition = Record<string, WhereValue>;
|
|
330
|
-
type SortDirection = 'asc' | 'desc';
|
|
331
|
-
type SortCondition = Record<string, SortDirection> | Record<string, SortDirection>[];
|
|
332
|
-
/**
|
|
333
|
-
* A relationship joined by name — a reference the fetched type declares, or a reverse one another
|
|
334
|
-
* type declares to it (`reviews`) — optionally filtered, counted and aliased:
|
|
335
|
-
* `{ relationship: 'products', where: { status: 'active' }, aggregate: 'count', alias: 'productCount' }`.
|
|
336
|
-
* `relationship` is a name, with no parentheses. A `select` reads what it joins.
|
|
337
|
-
*/
|
|
338
|
-
type IncludeRelationship = {
|
|
339
|
-
relationship: string;
|
|
340
|
-
where?: WhereCondition;
|
|
341
|
-
/**
|
|
342
|
-
* What the include answers instead of the entries it joins. `count` is the one modifier: `sum`,
|
|
343
|
-
* `avg`, `min` and `max` name no field to reduce — select one, like `products.price.sum` — and
|
|
344
|
-
* the service refuses them (REL-1479).
|
|
345
|
-
*/
|
|
346
|
-
aggregate?: 'count';
|
|
347
|
-
/** The name the include answers under; the relationship's name when absent */
|
|
348
|
-
alias?: string;
|
|
349
|
-
};
|
|
350
|
-
/**
|
|
351
|
-
* What a fetch includes (REL-2035). A string is an **include path**, the grammar `?include=` and the
|
|
352
|
-
* SDK's `include()` read: field ids joined by `.`, crossing lists, page builders, objects and
|
|
353
|
-
* references, each hop written out, with the fields to return in parentheses —
|
|
354
|
-
* `'sections.customers.logo'`, `'sections.features(name,slug)'`. The query returns what
|
|
355
|
-
* `GET …?include=` returns for the same paths. A path's entries are expanded after the read, so a
|
|
356
|
-
* `select` cannot read them: join a relationship for that ({@link IncludeRelationship}).
|
|
357
|
-
*/
|
|
358
|
-
type IncludeDefinition = string | (string | IncludeRelationship)[];
|
|
359
|
-
type SelectMapping = Record<string, string>;
|
|
360
|
-
/** `filters` are `where` conditions bound at call time: the same operators, written the same way. */
|
|
361
|
-
type FilterOperator = WhereOperator;
|
|
362
|
-
type FilterDefinition = Record<string, string | FilterOperator>;
|
|
363
|
-
/** A value that is either a literal or a `${param}` / `${param?default}` expression. */
|
|
364
|
-
type Parameterizable<T> = T | string;
|
|
365
|
-
type QueryParameterType = 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object';
|
|
366
|
-
/**
|
|
367
|
-
* A declared query parameter.
|
|
368
|
-
*
|
|
369
|
-
* Every `${...}` in a query and every `{name}` segment of its endpoint already declares one; this
|
|
370
|
-
* block adds a type and constraints. Nothing is inferred from a parameter's name.
|
|
371
|
-
*/
|
|
372
|
-
interface QueryParameter {
|
|
373
|
-
/** The parameter, as it appears in `${...}` or in an endpoint segment */
|
|
374
|
-
name: string;
|
|
375
|
-
/** Coerces the caller's value; a value that will not coerce is a 400 */
|
|
376
|
-
type?: QueryParameterType;
|
|
377
|
-
/** Overrides what the query's own expressions say */
|
|
378
|
-
required?: boolean;
|
|
379
|
-
/** Used when the caller supplies nothing */
|
|
380
|
-
default?: string | number | boolean | (string | number | boolean)[];
|
|
381
|
-
minimum?: number;
|
|
382
|
-
maximum?: number;
|
|
383
|
-
/** String characters, or array items */
|
|
384
|
-
minLength?: number;
|
|
385
|
-
maxLength?: number;
|
|
386
|
-
/** A regular expression, applied to strings */
|
|
387
|
-
pattern?: string;
|
|
388
|
-
enum?: (string | number | boolean)[];
|
|
389
|
-
}
|
|
390
|
-
/** Whether the query answers with one record or a list. Independent of how many rows match. */
|
|
391
|
-
type QueryCardinality = 'one' | 'many';
|
|
392
|
-
type CachePolicyObject = {
|
|
393
|
-
/** Defaults to `public` */
|
|
394
|
-
policy?: 'public' | 'private' | 'no-cache';
|
|
395
|
-
ttl?: number;
|
|
396
|
-
staleWhileRevalidate?: number;
|
|
397
|
-
tags?: string[];
|
|
398
|
-
};
|
|
399
|
-
type CachePolicy = string | CachePolicyObject;
|
|
400
|
-
/** A text search over `fields` the query runs beside its operation block. */
|
|
401
|
-
type FullTextSearch = {
|
|
402
|
-
/** The fields searched; at least one */
|
|
403
|
-
fields: string[];
|
|
404
|
-
/** The search text, usually a parameter expression such as `${q}` */
|
|
405
|
-
query: string;
|
|
406
|
-
highlight?: boolean;
|
|
407
|
-
ranking?: 'simple' | 'complex';
|
|
408
|
-
};
|
|
409
|
-
/**
|
|
410
|
-
* Fetch block - retrieve content entries
|
|
411
|
-
*/
|
|
412
|
-
interface FetchBlock {
|
|
413
|
-
/** Content type to fetch */
|
|
414
|
-
contentType?: string;
|
|
415
|
-
/** Singleton to fetch */
|
|
416
|
-
singleton?: string;
|
|
417
|
-
/** Filter conditions */
|
|
418
|
-
where?: WhereCondition;
|
|
419
|
-
/** Related content to include */
|
|
420
|
-
include?: IncludeDefinition;
|
|
421
|
-
/** Sort order */
|
|
422
|
-
sort?: SortCondition;
|
|
423
|
-
/** Maximum results */
|
|
424
|
-
limit?: Parameterizable<number>;
|
|
425
|
-
/** Results offset */
|
|
426
|
-
offset?: Parameterizable<number>;
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Aggregate block - perform aggregations
|
|
430
|
-
*/
|
|
431
|
-
interface AggregateBlock {
|
|
432
|
-
/** Source content type (required when not used with fetch) */
|
|
433
|
-
source?: string;
|
|
434
|
-
/** Filter conditions */
|
|
435
|
-
where?: WhereCondition;
|
|
436
|
-
/** Group by field(s) */
|
|
437
|
-
by?: string | string[] | (string | {
|
|
438
|
-
expression: string;
|
|
439
|
-
as?: string;
|
|
440
|
-
})[];
|
|
441
|
-
/**
|
|
442
|
-
* What to compute per group, keyed by the name each answers under: `<field>.<fn>`, where `fn` is
|
|
443
|
-
* `count`, `sum`, `avg`, `min`, `max`, `first` or `last` — `{ total: 'amount.sum' }`. Deploy
|
|
444
|
-
* requires it. The one spelling: `aggregations`, which this type called the main one, was a
|
|
445
|
-
* second name deploy refused (REL-1470).
|
|
446
|
-
*/
|
|
447
|
-
metrics?: Record<string, string>;
|
|
448
|
-
/** Having clause for filtering aggregations */
|
|
449
|
-
having?: Record<string, QueryScalar | HavingOperator>;
|
|
450
|
-
/** Sort order */
|
|
451
|
-
sort?: SortCondition;
|
|
452
|
-
/** Maximum results */
|
|
453
|
-
limit?: Parameterizable<number>;
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Search block - full-text and semantic search
|
|
457
|
-
*/
|
|
458
|
-
interface SearchBlock {
|
|
459
|
-
/** Single content type */
|
|
460
|
-
contentType?: string;
|
|
461
|
-
/** Multiple content types or "*" for all */
|
|
462
|
-
contentTypes?: string | string[] | '*';
|
|
463
|
-
/** Search query string */
|
|
464
|
-
query: string;
|
|
465
|
-
/** Fields to search in */
|
|
466
|
-
searchFields?: string[];
|
|
467
|
-
/** Legacy search type */
|
|
468
|
-
searchType?: 'plainto' | 'phraseto' | 'websearch' | 'to_tsquery';
|
|
469
|
-
/** Filter conditions */
|
|
470
|
-
where?: WhereCondition;
|
|
471
|
-
/** Field mapping for results */
|
|
472
|
-
fields?: SelectMapping;
|
|
473
|
-
/** Include relevance score */
|
|
474
|
-
includeRank?: boolean;
|
|
475
|
-
/** Include score breakdown */
|
|
476
|
-
explain?: boolean;
|
|
477
|
-
/** Highlight matching terms */
|
|
478
|
-
highlight?: boolean | {
|
|
479
|
-
field?: string;
|
|
480
|
-
maxWords?: number;
|
|
481
|
-
minWords?: number;
|
|
482
|
-
shortWord?: number;
|
|
483
|
-
};
|
|
484
|
-
/** Sort order */
|
|
485
|
-
sort?: SortCondition;
|
|
486
|
-
/** Maximum results */
|
|
487
|
-
limit?: Parameterizable<number>;
|
|
488
|
-
/** Results offset */
|
|
489
|
-
offset?: Parameterizable<number>;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Include sub-queries for additional data
|
|
493
|
-
*/
|
|
494
|
-
interface IncludeSubQuery {
|
|
495
|
-
source: string;
|
|
496
|
-
where?: WhereCondition;
|
|
497
|
-
sort?: SortCondition;
|
|
498
|
-
limit?: Parameterizable<number>;
|
|
499
|
-
select?: SelectMapping;
|
|
500
|
-
}
|
|
501
|
-
type IncludeSubQueries = Record<string, IncludeSubQuery>;
|
|
502
|
-
/**
|
|
503
|
-
* Which operation block a query runs. Inferred from the block it declares when absent.
|
|
504
|
-
*
|
|
505
|
-
* `similar` is not one: deploy refused a query built on it alone and nothing ran it. Similar
|
|
506
|
-
* content is `relyio.similar(uid)` (REL-1470).
|
|
507
|
-
*/
|
|
508
|
-
type QueryType = 'fetch' | 'aggregate' | 'search';
|
|
509
|
-
/**
|
|
510
|
-
* Query definition configuration
|
|
511
|
-
*/
|
|
512
|
-
interface QueryConfig {
|
|
513
|
-
/** Which operation block the query runs; inferred when absent */
|
|
514
|
-
type?: QueryType;
|
|
515
|
-
/** API endpoint path (required, e.g., /api/featured-products) */
|
|
516
|
-
endpoint: string;
|
|
517
|
-
/** Query description */
|
|
518
|
-
description?: string;
|
|
519
|
-
/** Fetch block for retrieving entries */
|
|
520
|
-
fetch?: FetchBlock;
|
|
521
|
-
/** Aggregate block for aggregations */
|
|
522
|
-
aggregate?: AggregateBlock;
|
|
523
|
-
/** Search block for full-text/semantic search */
|
|
524
|
-
search?: SearchBlock;
|
|
525
|
-
/** Include sub-queries */
|
|
526
|
-
include?: IncludeSubQueries;
|
|
527
|
-
/** Dynamic filter definitions */
|
|
528
|
-
filters?: FilterDefinition;
|
|
529
|
-
/** Full-text search over the fields it names */
|
|
530
|
-
fullText?: FullTextSearch;
|
|
531
|
-
/** Field selection/mapping */
|
|
532
|
-
select?: SelectMapping;
|
|
533
|
-
/** Cache policy */
|
|
534
|
-
cache?: CachePolicy;
|
|
535
|
-
/** Types and constraints for the parameters the query already declares by using them */
|
|
536
|
-
parameters?: QueryParameter[];
|
|
537
|
-
/** Whether the response is the record itself or a list. Defaults to `many` */
|
|
538
|
-
cardinality?: QueryCardinality;
|
|
539
|
-
}
|
|
540
|
-
/** A value a query parameter takes, as the query string carries it to the query. */
|
|
541
|
-
type QueryParameterValue = QueryScalar | readonly QueryScalar[];
|
|
542
|
-
/** What a query whose parameters no type states accepts: any name, any value. */
|
|
543
|
-
type AnyQueryParameters = {
|
|
544
|
-
readonly [name: string]: QueryParameterValue | undefined;
|
|
545
|
-
};
|
|
546
|
-
/** Type only: where a keyed definition keeps the parameters it declares (`InferQueryParams`). */
|
|
547
|
-
declare const parametersAs: unique symbol;
|
|
548
|
-
/**
|
|
549
|
-
* Query definition
|
|
550
|
-
*
|
|
551
|
-
* `TParameters` is what the query accepts, read from the definition as written (REL-2421); a
|
|
552
|
-
* definition typed by nothing more than this interface accepts any.
|
|
553
|
-
*/
|
|
554
|
-
interface QueryDefinition<TParameters extends object = AnyQueryParameters> {
|
|
555
|
-
/** Type only: never present at runtime. */
|
|
556
|
-
readonly [parametersAs]?: TParameters;
|
|
557
|
-
readonly _tag: 'query';
|
|
558
|
-
/** Written from its key by `defineSchema` */
|
|
559
|
-
readonly name?: string;
|
|
560
|
-
readonly type?: QueryType;
|
|
561
|
-
readonly endpoint: string;
|
|
562
|
-
readonly description?: string;
|
|
563
|
-
readonly fetch?: FetchBlock;
|
|
564
|
-
readonly aggregate?: AggregateBlock;
|
|
565
|
-
readonly search?: SearchBlock;
|
|
566
|
-
readonly include?: IncludeSubQueries;
|
|
567
|
-
readonly filters?: FilterDefinition;
|
|
568
|
-
readonly fullText?: FullTextSearch;
|
|
569
|
-
readonly select?: SelectMapping;
|
|
570
|
-
readonly cache?: CachePolicy;
|
|
571
|
-
readonly parameters?: QueryParameter[];
|
|
572
|
-
readonly cardinality?: QueryCardinality;
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Define a predefined query (REL-1969): it takes no name, because its key under `defineSchema`'s
|
|
576
|
-
* `queries` is its id. Its `where` is the one a list takes, its operators `$`-prefixed (REL-2439).
|
|
577
|
-
*
|
|
578
|
-
* @example
|
|
579
|
-
* defineSchema({
|
|
580
|
-
* contentTypes: { product },
|
|
581
|
-
* queries: {
|
|
582
|
-
* featuredProducts: defineQuery({
|
|
583
|
-
* endpoint: '/api/featured-products',
|
|
584
|
-
* fetch: { contentType: 'product', where: { featured: true }, limit: 10 },
|
|
585
|
-
* }),
|
|
586
|
-
* },
|
|
587
|
-
* })
|
|
588
|
-
*
|
|
589
|
-
* @example
|
|
590
|
-
* // queries: { featuredProducts }
|
|
591
|
-
* const featuredProducts = defineQuery({
|
|
592
|
-
* endpoint: '/api/featured-products',
|
|
593
|
-
* description: 'Get featured products for homepage',
|
|
594
|
-
* fetch: {
|
|
595
|
-
* contentType: 'product',
|
|
596
|
-
* where: {
|
|
597
|
-
* status: 'active',
|
|
598
|
-
* featured: true,
|
|
599
|
-
* },
|
|
600
|
-
* include: ['brand', 'categories'],
|
|
601
|
-
* sort: { publishedAt: 'desc' },
|
|
602
|
-
* limit: 10,
|
|
603
|
-
* },
|
|
604
|
-
* cache: {
|
|
605
|
-
* policy: 'public',
|
|
606
|
-
* ttl: 300,
|
|
607
|
-
* staleWhileRevalidate: 60,
|
|
608
|
-
* }
|
|
609
|
-
* })
|
|
610
|
-
*
|
|
611
|
-
* @example
|
|
612
|
-
* // queries: { searchProducts }
|
|
613
|
-
* const searchProducts = defineQuery({
|
|
614
|
-
* endpoint: '/api/search',
|
|
615
|
-
* description: 'Search products with semantic understanding',
|
|
616
|
-
* search: {
|
|
617
|
-
* contentType: 'product',
|
|
618
|
-
* query: '${q}',
|
|
619
|
-
* where: { status: 'active' },
|
|
620
|
-
* highlight: true,
|
|
621
|
-
* limit: 20,
|
|
622
|
-
* },
|
|
623
|
-
* filters: {
|
|
624
|
-
* 'price.base': { $gte: '${minPrice?0}', $lte: '${maxPrice?}' },
|
|
625
|
-
* category: '${categoryId?}',
|
|
626
|
-
* },
|
|
627
|
-
* cache: 'public 60s',
|
|
628
|
-
* })
|
|
629
|
-
*
|
|
630
|
-
* @example
|
|
631
|
-
* // queries: { productStats }
|
|
632
|
-
* const productStats = defineQuery({
|
|
633
|
-
* endpoint: '/api/products/stats',
|
|
634
|
-
* description: 'Get product statistics by category',
|
|
635
|
-
* aggregate: {
|
|
636
|
-
* source: 'product',
|
|
637
|
-
* where: { status: 'active' },
|
|
638
|
-
* by: ['category'],
|
|
639
|
-
* metrics: {
|
|
640
|
-
* totalProducts: 'id.count',
|
|
641
|
-
* avgPrice: 'price.base.avg',
|
|
642
|
-
* minPrice: 'price.base.min',
|
|
643
|
-
* maxPrice: 'price.base.max',
|
|
644
|
-
* },
|
|
645
|
-
* sort: { totalProducts: 'desc' },
|
|
646
|
-
* },
|
|
647
|
-
* cache: 'public 300s',
|
|
648
|
-
* })
|
|
649
|
-
*/
|
|
650
|
-
declare function defineQuery<const TConfig extends QueryConfig>(config: TConfig): QueryDefinition<DeclaredParameters<TConfig>>;
|
|
651
|
-
/**
|
|
652
|
-
* Infer basic response type from a query definition
|
|
653
|
-
* Note: For accurate types, use the codegen tool
|
|
654
|
-
*/
|
|
655
|
-
type InferQueryResponse<_T extends QueryDefinition> = unknown[];
|
|
656
|
-
/**
|
|
657
|
-
* The parameters a query accepts, by name (REL-2421): what `client.query(name, { params })` takes.
|
|
658
|
-
*
|
|
659
|
-
* Read from the keyed definition as written, as the API's `declareQueryParameters` reads the
|
|
660
|
-
* deployed one: each `{name}` segment of the endpoint (required — the route cannot match without
|
|
661
|
-
* it), each `${name}` in the definition's values (required) or `${name?…}` (optional), and each
|
|
662
|
-
* entry of `parameters`, whose `type` types the value and whose `required` decides. A name the
|
|
663
|
-
* query does not declare is not a parameter, so it does not compile.
|
|
664
|
-
*/
|
|
665
|
-
type InferQueryParams<T extends QueryDefinition<object>> = T extends QueryDefinition<infer P> ? P : AnyQueryParameters;
|
|
666
|
-
/** Every string value in `T`, at any depth — values only: a key is a field path, never a parameter. */
|
|
667
|
-
type StringsIn<T> = T extends string ? T : T extends readonly (infer Item)[] ? StringsIn<Item> : T extends object ? {
|
|
668
|
-
[K in keyof T]-?: StringsIn<T[K]>;
|
|
669
|
-
}[keyof T] : never;
|
|
670
|
-
/** The `${…}` expressions in one string, each as its name and whether it is optional. */
|
|
671
|
-
type ExpressionsIn<S extends string> = S extends `${string}\${${infer Body}}${infer Rest}` ? (Body extends `${infer Name}?${string}` ? {
|
|
672
|
-
readonly name: Name;
|
|
673
|
-
readonly optional: true;
|
|
674
|
-
} : {
|
|
675
|
-
readonly name: Body;
|
|
676
|
-
readonly optional: false;
|
|
677
|
-
}) | ExpressionsIn<Rest> : never;
|
|
678
|
-
/** The `{name}` segments of an endpoint. */
|
|
679
|
-
type EndpointNames<E> = E extends `${string}{${infer Name}}${infer Rest}` ? Name | EndpointNames<Rest> : never;
|
|
680
|
-
/** The expressions of a definition: its values but `parameters` and `description`, as the API scans. */
|
|
681
|
-
type Expressions<C> = ExpressionsIn<StringsIn<Omit<C, 'parameters' | 'description'>>>;
|
|
682
|
-
/** The `parameters` entries a definition declares. */
|
|
683
|
-
type Declared<C> = C extends {
|
|
684
|
-
readonly parameters: readonly (infer Entry)[];
|
|
685
|
-
} ? Entry : never;
|
|
686
|
-
/** What a declared `type` makes a value. */
|
|
687
|
-
type ValueOfType<T> = T extends 'string' ? string : T extends 'number' | 'integer' ? number : T extends 'boolean' ? boolean : T extends 'array' ? readonly QueryScalar[] : T extends 'object' ? never : QueryParameterValue;
|
|
688
|
-
/** What a definition declares, read once: its endpoint's segments, its expressions, its entries. */
|
|
689
|
-
type Declaration<C> = {
|
|
690
|
-
readonly segments: EndpointNames<C extends {
|
|
691
|
-
readonly endpoint: infer E;
|
|
692
|
-
} ? E : never>;
|
|
693
|
-
readonly expressions: Expressions<C>;
|
|
694
|
-
readonly entries: Declared<C>;
|
|
695
|
-
};
|
|
696
|
-
/** What any declaration is. */
|
|
697
|
-
interface AnyDeclaration {
|
|
698
|
-
readonly segments: string;
|
|
699
|
-
readonly expressions: {
|
|
700
|
-
readonly name: string;
|
|
701
|
-
readonly optional: boolean;
|
|
702
|
-
};
|
|
703
|
-
readonly entries: unknown;
|
|
704
|
-
}
|
|
705
|
-
/** Every name a declaration holds. */
|
|
706
|
-
type NamesOf<D extends AnyDeclaration> = D['segments'] | NameOf<D['expressions']> | NameOf<D['entries']>;
|
|
707
|
-
/**
|
|
708
|
-
* The names a union of expressions or entries holds. Distributive on purpose: none is `never`,
|
|
709
|
-
* which a bare `extends` would match and answer the constraint, `string`, for.
|
|
710
|
-
*/
|
|
711
|
-
type NameOf<E> = E extends {
|
|
712
|
-
readonly name: infer N extends string;
|
|
713
|
-
} ? N : never;
|
|
714
|
-
/** Whether `Name` is used bare (`${name}`) anywhere — which makes it required. */
|
|
715
|
-
type UsedBare<D extends AnyDeclaration, Name> = [
|
|
716
|
-
Extract<D['expressions'], {
|
|
717
|
-
readonly name: Name;
|
|
718
|
-
readonly optional: false;
|
|
719
|
-
}>
|
|
720
|
-
] extends [never] ? false : true;
|
|
721
|
-
/** The `parameters` entry naming `Name`, or `never` where none does. */
|
|
722
|
-
type EntryFor<D extends AnyDeclaration, Name> = Extract<D['entries'], {
|
|
723
|
-
readonly name: Name;
|
|
724
|
-
}>;
|
|
725
|
-
/**
|
|
726
|
-
* Whether `Name` is required: an endpoint segment always; else its entry's `required`; else an entry
|
|
727
|
-
* that says nothing about it is required unless some use says it is optional and none is bare; else
|
|
728
|
-
* any bare use. No entry is asked about first: `never` matches every shape.
|
|
729
|
-
*/
|
|
730
|
-
type IsRequired<D extends AnyDeclaration, Name> = [Name] extends [D['segments']] ? true : [EntryFor<D, Name>] extends [never] ? UsedBare<D, Name> : [EntryFor<D, Name>] extends [{
|
|
731
|
-
readonly required: infer R extends boolean;
|
|
732
|
-
}] ? R : [Extract<D['expressions'], {
|
|
733
|
-
readonly name: Name;
|
|
734
|
-
}>] extends [never] ? true : UsedBare<D, Name>;
|
|
735
|
-
/** The value `Name` takes: its entry's declared `type`, else any value a parameter takes. */
|
|
736
|
-
type ParameterValue<D extends AnyDeclaration, Name> = [EntryFor<D, Name>] extends [never] ? QueryParameterValue : [EntryFor<D, Name>] extends [{
|
|
737
|
-
readonly type: infer T;
|
|
738
|
-
}] ? ValueOfType<T> : QueryParameterValue;
|
|
739
|
-
type Simplify<T> = {
|
|
740
|
-
[K in keyof T]: T[K];
|
|
741
|
-
} & {};
|
|
742
|
-
/** The parameters a keyed definition declares: required ones required, the rest optional. */
|
|
743
|
-
type DeclaredParameters<C> = ParametersOf<Declaration<C>>;
|
|
744
|
-
type ParametersOf<D extends AnyDeclaration> = Simplify<{
|
|
745
|
-
readonly [Name in NamesOf<D> as IsRequired<D, Name> extends true ? Name : never]: ParameterValue<D, Name>;
|
|
746
|
-
} & {
|
|
747
|
-
readonly [Name in NamesOf<D> as IsRequired<D, Name> extends true ? never : Name]?: ParameterValue<D, Name>;
|
|
748
|
-
}>;
|
|
749
|
-
|
|
750
|
-
/**
|
|
751
|
-
* Schema definition matching @relyio/schema SchemaDefinitionSchema
|
|
752
|
-
*
|
|
753
|
-
* Note: `version` is NOT user-defined - it's auto-generated by the backend.
|
|
754
|
-
*/
|
|
755
|
-
|
|
756
|
-
/**
|
|
757
|
-
* Schema configuration
|
|
758
|
-
*
|
|
759
|
-
* Matches the SchemaDefinitionSchema from @relyio/schema:
|
|
760
|
-
* - locales: Optional array of locale definitions for multi-language support
|
|
761
|
-
* - contentTypes: Required record of content type definitions
|
|
762
|
-
* - singletonContentTypes: Required record of singleton definitions (can be empty {})
|
|
763
|
-
* - queries: Required record of query definitions (can be empty {})
|
|
764
|
-
* - settingsGroups: Optional record of settings groups
|
|
765
|
-
* - roles: Optional record of custom roles, each keyed by its id
|
|
766
|
-
* - workflow: Optional workflow configuration with approval stages
|
|
767
|
-
*
|
|
768
|
-
* Note: `version` is auto-generated by the backend, not user-defined!
|
|
769
|
-
*/
|
|
770
|
-
interface SchemaConfig {
|
|
771
|
-
/** Locale definitions for multi-language support (optional) */
|
|
772
|
-
locales?: LocaleDefinition[];
|
|
773
|
-
/** Content type definitions (required) */
|
|
774
|
-
contentTypes: Record<string, ContentTypeDefinition>;
|
|
775
|
-
/** Singleton content type definitions (required, can be empty) */
|
|
776
|
-
singletonContentTypes?: Record<string, SingletonContentTypeDefinition>;
|
|
777
|
-
/** Predefined query definitions (required, can be empty) */
|
|
778
|
-
queries?: Record<string, QueryDefinition>;
|
|
779
|
-
/** Settings group definitions (optional) */
|
|
780
|
-
settingsGroups?: Record<string, SettingsGroupDefinition>;
|
|
781
|
-
/** Asset type definitions (optional) */
|
|
782
|
-
assetTypes?: Record<string, AssetTypeDefinition>;
|
|
783
|
-
/** Record type definitions: the data the app writes while it runs (optional, spec 1) */
|
|
784
|
-
recordTypes?: Record<string, RecordTypeDefinition>;
|
|
785
|
-
/** Custom roles for fine-grained access control, each under its id (optional) */
|
|
786
|
-
roles?: KeyedRoles;
|
|
787
|
-
/** Global workflow configuration with approval stages (optional) */
|
|
788
|
-
workflow?: WorkflowDefinition;
|
|
789
|
-
/** Pre-configured entry list views, each under its id (optional) */
|
|
790
|
-
views?: KeyedViews;
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* Complete schema definition - Generic version for type inference
|
|
794
|
-
*/
|
|
795
|
-
interface SchemaDefinition<TContentTypes extends Record<string, ContentTypeDefinition> = Record<string, ContentTypeDefinition>, TSingletons extends Record<string, SingletonContentTypeDefinition> = Record<string, SingletonContentTypeDefinition>, TQueries extends Record<string, QueryDefinition> = Record<string, QueryDefinition>, TSettings extends Record<string, SettingsGroupDefinition> = Record<string, SettingsGroupDefinition>, TLocales extends readonly LocaleDefinition[] = readonly LocaleDefinition[], TRoles extends readonly RoleDefinition[] = readonly RoleDefinition[], TWorkflow extends WorkflowDefinition | undefined = WorkflowDefinition | undefined, TViews extends readonly ViewDefinition[] = readonly ViewDefinition[], TAssets extends Record<string, AssetTypeDefinition> = Record<string, AssetTypeDefinition>, TRecords extends Record<string, RecordTypeDefinition> = Record<string, RecordTypeDefinition>> {
|
|
796
|
-
readonly _tag: 'schema';
|
|
797
|
-
readonly locales?: TLocales;
|
|
798
|
-
readonly contentTypes: TContentTypes;
|
|
799
|
-
readonly singletonContentTypes: TSingletons;
|
|
800
|
-
readonly queries: TQueries;
|
|
801
|
-
readonly settingsGroups?: TSettings;
|
|
802
|
-
readonly assetTypes?: TAssets;
|
|
803
|
-
readonly recordTypes?: TRecords;
|
|
804
|
-
readonly roles?: TRoles;
|
|
805
|
-
readonly workflow?: TWorkflow;
|
|
806
|
-
readonly views?: TViews;
|
|
807
|
-
}
|
|
808
|
-
/**
|
|
809
|
-
* Typed schema config for type inference
|
|
810
|
-
*/
|
|
811
|
-
interface TypedSchemaConfig<TContentTypes extends Record<string, ContentTypeDefinition>, TSingletons extends Record<string, SingletonContentTypeDefinition>, TQueries extends Record<string, QueryDefinition>, TSettings extends Record<string, SettingsGroupDefinition>, TLocales extends readonly LocaleDefinition[] = readonly LocaleDefinition[], TRoles extends KeyedRoles = KeyedRoles, TWorkflow extends WorkflowDefinition | undefined = WorkflowDefinition | undefined, TViews extends KeyedViews = KeyedViews, TAssets extends Record<string, AssetTypeDefinition> = Record<string, AssetTypeDefinition>, TRecords extends Record<string, RecordTypeDefinition> = Record<string, RecordTypeDefinition>> {
|
|
812
|
-
locales?: TLocales;
|
|
813
|
-
contentTypes: TContentTypes;
|
|
814
|
-
singletonContentTypes?: TSingletons;
|
|
815
|
-
queries?: TQueries;
|
|
816
|
-
settingsGroups?: TSettings;
|
|
817
|
-
assetTypes?: TAssets;
|
|
818
|
-
recordTypes?: TRecords;
|
|
819
|
-
roles?: TRoles;
|
|
820
|
-
workflow?: TWorkflow;
|
|
821
|
-
views?: TViews;
|
|
822
|
-
}
|
|
823
|
-
/**
|
|
824
|
-
* Define a complete schema
|
|
825
|
-
*
|
|
826
|
-
* This creates a schema definition that can be:
|
|
827
|
-
* 1. Deployed via the CLI
|
|
828
|
-
* 2. Used for type inference in the SDK client
|
|
829
|
-
*
|
|
830
|
-
* @example
|
|
831
|
-
* import { defineSchema, defineContentType, defineLocale, fields, fieldset } from '@relyio/sdk/schema'
|
|
832
|
-
*
|
|
833
|
-
* const enUS = defineLocale('en-US', { displayName: 'English (US)', default: true })
|
|
834
|
-
* const esES = defineLocale('es-ES', { displayName: 'Spanish', fallback: ['en-US'] })
|
|
835
|
-
*
|
|
836
|
-
* const product = defineContentType({
|
|
837
|
-
* fields: {
|
|
838
|
-
* title: fields.shortText({ required: true, localized: true }),
|
|
839
|
-
* price: fields.decimal({ min: 0, decimalPlaces: 2 }),
|
|
840
|
-
* // One value of a fieldset: `{ _type: 'seo', _key, metaTitle?, metaDescription? }`
|
|
841
|
-
* seo: fields.object({
|
|
842
|
-
* of: fieldset('seo', {
|
|
843
|
-
* displayName: 'SEO metadata',
|
|
844
|
-
* fields: {
|
|
845
|
-
* metaTitle: fields.shortText({ maxLength: 60 }),
|
|
846
|
-
* metaDescription: fields.longText({ maxLength: 160 }),
|
|
847
|
-
* },
|
|
848
|
-
* }),
|
|
849
|
-
* }),
|
|
850
|
-
* },
|
|
851
|
-
* })
|
|
852
|
-
*
|
|
853
|
-
* export const schema = defineSchema({
|
|
854
|
-
* locales: [enUS, esES],
|
|
855
|
-
* contentTypes: { product },
|
|
856
|
-
* })
|
|
857
|
-
*/
|
|
858
|
-
declare function defineSchema<TContentTypes extends Record<string, ContentTypeDefinition>, TSingletons extends Record<string, SingletonContentTypeDefinition> = Record<string, never>, TQueries extends Record<string, QueryDefinition> = Record<string, never>, TSettings extends Record<string, SettingsGroupDefinition> = Record<string, never>, TLocales extends readonly LocaleDefinition[] = readonly never[], TRoles extends KeyedRoles = Record<never, never>, TWorkflow extends WorkflowDefinition | undefined = undefined, TViews extends KeyedViews = Record<never, never>, TAssets extends Record<string, AssetTypeDefinition> = Record<string, never>, TRecords extends Record<string, RecordTypeDefinition> = Record<string, never>>(config: TypedSchemaConfig<TContentTypes, TSingletons, TQueries, TSettings, TLocales, TRoles, TWorkflow, TViews, TAssets, TRecords> & NamesChecked<TContentTypes, TSingletons, TSettings, TAssets, TRecords, TLocales, TRoles, TWorkflow>): SchemaDefinition<TContentTypes, TSingletons, TQueries, TSettings, TLocales, RolesAsList<TRoles>, TWorkflow, ViewsAsList<TViews>, TAssets, TRecords>;
|
|
859
|
-
/**
|
|
860
|
-
* What `defineSchema` holds a schema's names to (REL-2416): each section of types against what the
|
|
861
|
-
* schema declares — a reference's `to` and rich text's `links.to` against its content, singleton and
|
|
862
|
-
* asset type keys (a reference may point at a singleton: `@relyio/schema`'s
|
|
863
|
-
* `ResolvedReferenceTarget`), and a Field's `requiredLocales` against its locale codes; its locales'
|
|
864
|
-
* `fallback` against their codes; the roles its workflow's stages name, and its roles' `includes`,
|
|
865
|
-
* against the built-in roles and its role keys; and a type's stages against its workflow's stage
|
|
866
|
-
* keys. Types only; `./checked-names.ts` says how.
|
|
867
|
-
*/
|
|
868
|
-
type NamesChecked<TContentTypes, TSingletons, TSettings, TAssets, TRecords, TLocales, TRoles, TWorkflow> = {
|
|
869
|
-
readonly locales?: CheckedLocales<TLocales>;
|
|
870
|
-
readonly roles?: CheckedRoles<TRoles>;
|
|
871
|
-
readonly workflow?: CheckedWorkflow<TWorkflow, TRoles>;
|
|
872
|
-
readonly contentTypes: CheckedSection<TContentTypes, DeclaredBy<TContentTypes, TSingletons, TAssets, TLocales, TWorkflow>>;
|
|
873
|
-
readonly singletonContentTypes?: CheckedSection<TSingletons, DeclaredBy<TContentTypes, TSingletons, TAssets, TLocales, TWorkflow>>;
|
|
874
|
-
readonly settingsGroups?: CheckedSection<TSettings, DeclaredBy<TContentTypes, TSingletons, TAssets, TLocales, TWorkflow>>;
|
|
875
|
-
readonly assetTypes?: CheckedSection<TAssets, DeclaredBy<TContentTypes, TSingletons, TAssets, TLocales, TWorkflow>>;
|
|
876
|
-
readonly recordTypes?: CheckedSection<TRecords, DeclaredBy<TContentTypes, TSingletons, TAssets, TLocales, TWorkflow, TRecords>>;
|
|
877
|
-
};
|
|
878
|
-
/**
|
|
879
|
-
* The names a schema declares, for its sections' names to be checked against. `TRecords` is the
|
|
880
|
-
* Record types a section's references may name: none for an entry type's.
|
|
881
|
-
*/
|
|
882
|
-
interface DeclaredBy<TContentTypes, TSingletons, TAssets, TLocales, TWorkflow, TRecords = never> {
|
|
883
|
-
readonly targets: KeysDeclared<TContentTypes> | KeysDeclared<TSingletons> | KeysDeclared<TAssets> | KeysDeclared<TRecords> | ([TRecords] extends [never] ? never : ContributedRecordType);
|
|
884
|
-
readonly locales: LocaleCodesOf<TLocales>;
|
|
885
|
-
readonly stages: StagesDeclared<TWorkflow>;
|
|
886
|
-
}
|
|
887
|
-
/**
|
|
888
|
-
* The roles `defineSchema` returns for the keyed record it was given: the list it compiles to, each
|
|
889
|
-
* role carrying its key as a literal `id` (REL-2414).
|
|
890
|
-
*/
|
|
891
|
-
type RolesAsList<R extends KeyedRoles> = KeyedRolesAsList<R>;
|
|
892
|
-
/** The views `defineSchema` returns for the ones it was given, as {@link RolesAsList} says of roles. */
|
|
893
|
-
type ViewsAsList<V extends KeyedViews> = KeyedViewsAsList<V>;
|
|
894
|
-
/**
|
|
895
|
-
* Type alias for any schema definition.
|
|
896
|
-
* Uses `any` intentionally for type inference utilities that need to accept any schema.
|
|
897
|
-
*/
|
|
898
|
-
type AnySchemaDefinition = SchemaDefinition<any, any, any, any, any, any, any, any, any, any>;
|
|
899
|
-
/**
|
|
900
|
-
* Get content type names from a schema
|
|
901
|
-
*/
|
|
902
|
-
type SchemaContentTypeNames<T extends AnySchemaDefinition> = keyof T['contentTypes'] & string;
|
|
903
|
-
/**
|
|
904
|
-
* An entry of content type `K`, typed by schema `T` as a read returns it — what `content(K)` reads,
|
|
905
|
-
* with references resolved against `T` (`INV-SS-TYPES-INFERRED`).
|
|
906
|
-
*/
|
|
907
|
-
type SchemaEntry<T extends AnySchemaDefinition, K extends SchemaContentTypeNames<T>> = InferContentType<T['contentTypes'][K], T>;
|
|
908
|
-
/**
|
|
909
|
-
* An entry of any one of the content types `K` names — every content type by default — as a search
|
|
910
|
-
* across them returns it: a union, so `_metadata.type` tells a caller which it holds.
|
|
911
|
-
*/
|
|
912
|
-
type SchemaEntryOf<T extends AnySchemaDefinition, K extends SchemaContentTypeNames<T> = SchemaContentTypeNames<T>> = {
|
|
913
|
-
[N in K]: SchemaEntry<T, N>;
|
|
914
|
-
}[K];
|
|
915
|
-
/**
|
|
916
|
-
* Get singleton names from a schema
|
|
917
|
-
*/
|
|
918
|
-
type SchemaSingletonNames<T extends AnySchemaDefinition> = keyof T['singletonContentTypes'] & string;
|
|
919
|
-
/**
|
|
920
|
-
* Get query names from a schema
|
|
921
|
-
*/
|
|
922
|
-
type SchemaQueryNames<T extends AnySchemaDefinition> = keyof T['queries'] & string;
|
|
923
|
-
/**
|
|
924
|
-
* Get settings group names from a schema.
|
|
925
|
-
*
|
|
926
|
-
* `settingsGroups`, `assetTypes` and `locales` are optional members of `SchemaDefinition`, so
|
|
927
|
-
* indexing one yields `X | undefined`, which never extends the record — every typed client's
|
|
928
|
-
* `settings()`, `asset()` and `with({ locale })` took `never`. The three read through `NonNullable`.
|
|
929
|
-
*/
|
|
930
|
-
type SchemaSettingsGroupNames<T extends AnySchemaDefinition> = NonNullable<T['settingsGroups']> extends Record<string, SettingsGroupDefinition> ? keyof NonNullable<T['settingsGroups']> & string : never;
|
|
931
|
-
/**
|
|
932
|
-
* Get asset type names from a schema
|
|
933
|
-
*/
|
|
934
|
-
type SchemaAssetTypeNames<T extends AnySchemaDefinition> = NonNullable<T['assetTypes']> extends Record<string, AssetTypeDefinition> ? keyof NonNullable<T['assetTypes']> & string : never;
|
|
935
|
-
/**
|
|
936
|
-
* Get Record type names from a schema (spec 1), read through `NonNullable` as asset types are
|
|
937
|
-
*/
|
|
938
|
-
type SchemaRecordTypeNames<T extends AnySchemaDefinition> = NonNullable<T['recordTypes']> extends Record<string, RecordTypeDefinition> ? keyof NonNullable<T['recordTypes']> & string : never;
|
|
939
|
-
/**
|
|
940
|
-
* Get locale codes from a schema: the codes its locales declare, or `string` for a schema that
|
|
941
|
-
* declares none. `defineSchema` now types an absent `locales` as an empty list, so that a Field's
|
|
942
|
-
* `requiredLocales` is checked against no locale (REL-2416); a read's locale keeps what it took
|
|
943
|
-
* before — any code — until the read options check it (REL-2417).
|
|
944
|
-
*/
|
|
945
|
-
type SchemaLocaleCodes<T extends AnySchemaDefinition> = NonNullable<T['locales']> extends readonly LocaleDefinition[] ? [NonNullable<T['locales']>[number]] extends [never] ? string : NonNullable<T['locales']>[number]['code'] : never;
|
|
946
|
-
|
|
947
|
-
export { type Parameterizable as $, type AnyRecordTypeDefinition as A, type WhereCondition as B, type WhereValue as C, type WhereOperator as D, type QueryScalar as E, type FieldsWriteRule as F, type SortCondition as G, type HavingOperator as H, type InferRecordType as I, type SortDirection as J, type KeyedRecordTypeConfig as K, type IncludeDefinition as L, type IncludeRelationship as M, type NamedPolicyRule as N, type OwnerDeletedAction as O, type PolicyRule as P, type QueryConfig as Q, type RolesAsList as R, type SchemaConfig as S, type SelectMapping as T, type FilterDefinition as U, type ViewsAsList as V, type WriteRule as W, type CachePolicy as X, type CachePolicyObject as Y, type IncludeSubQuery as Z, type IncludeSubQueries as _, type SchemaDefinition as a, type QueryParameter as a0, type QueryParameterType as a1, type QueryCardinality as a2, type InferQueryResponse as a3, type InferQueryParams as a4, type QueryParameterValue as a5, type AnyQueryParameters as a6, type DeclaredParameters as a7, type SchemaContentTypeNames as b, type SchemaSingletonNames as c, defineSchema as d, type SchemaQueryNames as e, type SchemaLocaleCodes as f, type SchemaSettingsGroupNames as g, type SchemaAssetTypeNames as h, type SchemaRecordTypeNames as i, type SchemaEntry as j, type SchemaEntryOf as k, defineRecordType as l, type RecordTypeDefinition as m, type RecordExpiry as n, type RecordFieldsOf as o, type RecordTypeEndUsers as p, type RecordUpdateFieldsOf as q, type RecordWriteFieldsOf as r, type RecordWriteRule as s, defineQuery as t, type QueryDefinition as u, type QueryType as v, type FullTextSearch as w, type FetchBlock as x, type AggregateBlock as y, type SearchBlock as z };
|