@foir/sdk 0.7.0 → 0.9.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 +857 -4
- package/README.md +46 -15
- package/dist/auth/auth.d.ts +104 -1
- package/dist/auth/hosted.d.ts +22 -0
- package/dist/auth/index.d.ts +13 -7
- package/dist/auth/operations.d.ts +85 -64
- package/dist/auth/ops.d.ts +99 -0
- package/dist/auth.js +786 -106
- package/dist/chunk-IGNLWT3H.js +35 -0
- package/dist/chunk-OHYVKTGB.js +45 -0
- package/dist/chunk-TAL5H6VA.js +39 -0
- package/dist/client.js +25 -31
- package/dist/codegen/block-registry.d.ts +13 -19
- package/dist/codegen/block-registry.js +3 -31
- package/dist/codegen/block-scaffold.d.ts +12 -21
- package/dist/codegen/block-scaffold.js +3 -41
- package/dist/codegen/index.d.ts +9 -4
- package/dist/codegen/index.js +7 -11
- package/dist/codegen/item-registry.d.ts +28 -0
- package/dist/codegen/item-registry.js +7 -0
- package/dist/codegen/item-scaffold.d.ts +29 -0
- package/dist/codegen/item-scaffold.js +7 -0
- package/dist/codegen/preset.d.ts +14 -7
- package/dist/codegen/shared.d.ts +20 -9
- package/dist/content/content-renderer.d.ts +90 -24
- package/dist/content/index.d.ts +13 -7
- package/dist/content/richtext.d.ts +66 -18
- package/dist/content.js +227 -80
- package/dist/data/builtins.d.ts +369 -92
- package/dist/data/client.d.ts +97 -25
- package/dist/data/document.d.ts +251 -0
- package/dist/data/index.d.ts +38 -19
- package/dist/data/manifest.d.ts +290 -8
- package/dist/data/schema.d.ts +78 -8
- package/dist/data/selection.d.ts +231 -37
- package/dist/data/subjects.d.ts +221 -0
- package/dist/data/subscription-document.d.ts +75 -0
- package/dist/data/subscriptions.d.ts +181 -0
- package/dist/data/transport.d.ts +255 -37
- package/dist/data/ws-transport.d.ts +197 -0
- package/dist/data.js +1419 -45
- package/dist/graphql/cdn-route.d.ts +12 -28
- package/dist/media/index.d.ts +6 -2
- package/dist/media/media.d.ts +2 -2
- package/dist/media/screen-capture.d.ts +81 -0
- package/dist/media.js +97 -0
- package/dist/next.js +663 -182
- package/dist/push.js +700 -90
- package/dist/react/FoirFeedback.d.ts +62 -0
- package/dist/react/feedback-notes.d.ts +101 -0
- package/dist/react/index.d.ts +7 -1
- package/dist/react.js +1272 -194
- package/dist/realtime.js +1 -1
- package/dist/server/events-client.d.ts +279 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server.js +298 -0
- package/dist/transport/foir-http.d.ts +23 -6
- package/dist/transport/persisted-query.d.ts +68 -0
- package/dist/transport/retry.d.ts +1 -1
- package/package.json +13 -1
- package/dist/chunk-ADO5FJNM.js +0 -30
package/dist/data/builtins.d.ts
CHANGED
|
@@ -7,24 +7,27 @@
|
|
|
7
7
|
* give four projects four chances to disagree about `ImageValue`.
|
|
8
8
|
*
|
|
9
9
|
* 1. **Value objects.** `GET /v1/manifest` reports a scalar's `type` as a
|
|
10
|
-
* GraphQL named type, and
|
|
11
|
-
* objects rather than leaves: `
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* 2. **
|
|
17
|
-
* for
|
|
18
|
-
* `
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
10
|
+
* GraphQL named type, and several of the names it can use are
|
|
11
|
+
* platform-owned objects rather than leaves: `Image`, `Video`, `FileValue`,
|
|
12
|
+
* `Richtext`, `GeoPoint`, `Reference`, `CollabInfo`. They are structurally
|
|
13
|
+
* nested but behave as leaves — always present, never lazily hydrated,
|
|
14
|
+
* never `include`-able.
|
|
15
|
+
*
|
|
16
|
+
* 2. **Primitive members.** A flexible field's union members are *model keys*,
|
|
17
|
+
* except for six lowercase tokens — `richtext`, `image`, `video`, `file`,
|
|
18
|
+
* `reference`, `geopoint` — which are members of the real GraphQL union but
|
|
19
|
+
* have **no entry in `models`**. A generator that resolved every member to
|
|
20
|
+
* `models[key]` would skip them (an inexhaustive union, silently wrong at
|
|
21
|
+
* runtime) or emit `never`.
|
|
22
|
+
*
|
|
23
|
+
* # These are ONE set, not two (TTS-1391)
|
|
24
|
+
*
|
|
25
|
+
* They used to be two: a value object for a plain field, and a separate
|
|
26
|
+
* `<Name>Block` wrapper for the same thing inside a flexible field. TTS-1391
|
|
27
|
+
* removed the wrapper — an item IS its value — so a plain `image` field and an
|
|
28
|
+
* `image` inside a flexible field are the SAME GraphQL type, `Image`. There is
|
|
29
|
+
* no `ImageValue` in a real schema and never will be again; the only difference
|
|
30
|
+
* between the two positions is whether `__typename` was selected.
|
|
28
31
|
*
|
|
29
32
|
* ---------------------------------------------------------------------------
|
|
30
33
|
* The obligation that comes with a static table
|
|
@@ -42,6 +45,7 @@
|
|
|
42
45
|
* Field shapes verified against deployed dev's introspection on 2026-07-28 and
|
|
43
46
|
* against `api-public/internal/schema/field_mapping.go`.
|
|
44
47
|
*/
|
|
48
|
+
import type { FoirConnection } from './schema';
|
|
45
49
|
/** A `JSON` scalar. Deliberately not `any`: reading through it needs a check. */
|
|
46
50
|
export type FoirJsonValue = string | number | boolean | null | FoirJsonValue[] | {
|
|
47
51
|
[key: string]: FoirJsonValue;
|
|
@@ -69,8 +73,18 @@ export interface ImageVariantSet {
|
|
|
69
73
|
_3xl: ImageVariant | null;
|
|
70
74
|
_4xl: ImageVariant | null;
|
|
71
75
|
}
|
|
72
|
-
export interface
|
|
73
|
-
|
|
76
|
+
export interface Image {
|
|
77
|
+
/**
|
|
78
|
+
* `String` on the wire, not `String!`.
|
|
79
|
+
*
|
|
80
|
+
* It was non-null here and nullable on the flexible-field member until
|
|
81
|
+
* TTS-1391, which is a §5.3.2 response-shape conflict the moment both are one
|
|
82
|
+
* type. The platform relaxed rather than tightened, because nullable is the
|
|
83
|
+
* honest form — its own public `File` asset type already declares
|
|
84
|
+
* `url: String` — so this follows.
|
|
85
|
+
*/
|
|
86
|
+
__typename?: 'Image';
|
|
87
|
+
url: string | null;
|
|
74
88
|
width: number | null;
|
|
75
89
|
height: number | null;
|
|
76
90
|
alt: string | null;
|
|
@@ -86,8 +100,9 @@ export interface ImageValue {
|
|
|
86
100
|
/** AVIF tier set (smaller, narrower support). The preferred `<picture>` source. */
|
|
87
101
|
avif: ImageVariantSet | null;
|
|
88
102
|
}
|
|
89
|
-
export interface
|
|
90
|
-
|
|
103
|
+
export interface Video {
|
|
104
|
+
__typename?: 'Video';
|
|
105
|
+
url: string | null;
|
|
91
106
|
thumbnailUrl: string | null;
|
|
92
107
|
previewUrl: string | null;
|
|
93
108
|
hlsManifestUrl: string | null;
|
|
@@ -100,28 +115,129 @@ export interface VideoValue {
|
|
|
100
115
|
fileSize: number | null;
|
|
101
116
|
}
|
|
102
117
|
export interface FileValue {
|
|
118
|
+
__typename?: 'FileValue';
|
|
103
119
|
url: string | null;
|
|
104
120
|
filename: string | null;
|
|
105
121
|
mimeType: string | null;
|
|
106
122
|
size: number | null;
|
|
107
123
|
}
|
|
108
|
-
export interface
|
|
124
|
+
export interface GeoPoint {
|
|
125
|
+
__typename?: 'GeoPoint';
|
|
109
126
|
lat: number | null;
|
|
110
127
|
lng: number | null;
|
|
111
128
|
}
|
|
112
|
-
export interface
|
|
129
|
+
export interface Richtext {
|
|
130
|
+
__typename?: 'Richtext';
|
|
113
131
|
html: string | null;
|
|
114
132
|
json: FoirJsonValue | null;
|
|
115
133
|
markdown: string | null;
|
|
116
134
|
}
|
|
117
135
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
136
|
+
* One run of styled text inside a passage.
|
|
137
|
+
*
|
|
138
|
+
* `marks` are named — `strong`, `em`, `code`, or a key into the passage's
|
|
139
|
+
* `markDefs` for anything that carries data (a link, and nothing else today).
|
|
140
|
+
* The bitmask the old editor stored is gone.
|
|
141
|
+
*/
|
|
142
|
+
export interface ProseSpan {
|
|
143
|
+
__typename?: 'ProseSpan';
|
|
144
|
+
text: string | null;
|
|
145
|
+
marks: Array<string | null> | null;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A text entry in a prose flow — a paragraph, a heading, a quote, a list item.
|
|
149
|
+
*
|
|
150
|
+
* `kind` is the semantic shape and `token` is the design-token override that
|
|
151
|
+
* beats it when set. `list` + `level` carry list nesting flat rather than as a
|
|
152
|
+
* tree. A soft break inside a passage is a `\n` in a span's text, not a
|
|
153
|
+
* separate entry.
|
|
154
|
+
*
|
|
155
|
+
* `markDefs` stays an open JSON leaf by declaration: def types are extensible,
|
|
156
|
+
* and a typed object over an open shape would drop what it does not know.
|
|
157
|
+
*/
|
|
158
|
+
export interface Passage {
|
|
159
|
+
__typename?: 'Passage';
|
|
160
|
+
_key: string | null;
|
|
161
|
+
kind: string | null;
|
|
162
|
+
token: string | null;
|
|
163
|
+
align: string | null;
|
|
164
|
+
list: string | null;
|
|
165
|
+
level: number | null;
|
|
166
|
+
language: string | null;
|
|
167
|
+
spans: Array<ProseSpan | null> | null;
|
|
168
|
+
markDefs: FoirJsonValue | null;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A prose field's read projection.
|
|
172
|
+
*
|
|
173
|
+
* `entries` is the typed reading and the one that keeps prose structured —
|
|
174
|
+
* `Passage` for a text-only field, and a union of `Passage` with the field's
|
|
175
|
+
* admitted embeds for one that places models. `html` and `markdown` are the
|
|
176
|
+
* passages only: an embed is omitted from both BY DECLARATION rather than
|
|
177
|
+
* rendered as invented markup, so a consumer that wants the embeds reads
|
|
178
|
+
* `entries`. `json` is the declared flow verbatim — the lossless escape hatch
|
|
179
|
+
* where an entry nobody recognises always survives.
|
|
180
|
+
*
|
|
181
|
+
* `E` is the entries element, filled in per field by `foir types`.
|
|
182
|
+
*/
|
|
183
|
+
export interface Prose<E = Passage> {
|
|
184
|
+
html: string | null;
|
|
185
|
+
markdown: string | null;
|
|
186
|
+
json: FoirJsonValue | null;
|
|
187
|
+
entries: Array<E | null> | null;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* One ancestor of a hierarchy record, root-first.
|
|
191
|
+
*
|
|
192
|
+
* Identity only, by design: a child's public URL already exposes every
|
|
193
|
+
* ancestor's slug, so the walk never widens content visibility. Anything more
|
|
194
|
+
* than identity goes through the `parent` reference like any other read.
|
|
121
195
|
*/
|
|
122
|
-
export interface
|
|
123
|
-
|
|
124
|
-
|
|
196
|
+
export interface RecordAncestor {
|
|
197
|
+
__typename?: 'RecordAncestor';
|
|
198
|
+
_id: string;
|
|
199
|
+
_naturalKey: string | null;
|
|
200
|
+
_modelKey: string | null;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* A reference whose target model is not pinned by the field's declaration.
|
|
204
|
+
*
|
|
205
|
+
* A reference field that declares ONE `referenceTypes` entry resolves to that
|
|
206
|
+
* model's own type, and one declaring several resolves to a `<Members>Ref`
|
|
207
|
+
* union — so this type is what an undeclared reference resolves to, and what a
|
|
208
|
+
* flexible field's `reference` member is.
|
|
209
|
+
*
|
|
210
|
+
* # What makes it followable
|
|
211
|
+
*
|
|
212
|
+
* `_targetModelKey` names the model and `_targetId` OR `_targetNaturalKey`
|
|
213
|
+
* identifies the row within it: `foir[_targetModelKey].findUnique({ where: { _id:
|
|
214
|
+
* _targetId } })`. Both identifier shapes are live — on the dev database 101 of
|
|
215
|
+
* 193 stored reference values carry an id and 92 carry a natural key and no id
|
|
216
|
+
* — so a consumer must handle either.
|
|
217
|
+
*
|
|
218
|
+
* `_id` and `_type` are NOT here, and their absence is the TTS-1391 correction
|
|
219
|
+
* rather than an omission. They were the wrapper's own metadata: `_id` was the
|
|
220
|
+
* ITEM's id (never the target's, which is why `_targetId` exists separately) and
|
|
221
|
+
* `_type` was the union discriminator, reading `"reference"` on every reference
|
|
222
|
+
* ever stored. The wrapper is gone, so neither field is in the schema, and a
|
|
223
|
+
* consumer selecting them got `undefined` while the types promised a string.
|
|
224
|
+
*/
|
|
225
|
+
export interface Reference<TRecord = FoirUnexpandedRecord> {
|
|
226
|
+
__typename?: 'Reference';
|
|
227
|
+
/** The model to fetch the target from. Null when the target no longer exists. */
|
|
228
|
+
_targetModelKey: string | null;
|
|
229
|
+
/** The target's id, when the reference stored one. */
|
|
230
|
+
_targetId: string | null;
|
|
231
|
+
/** The target's natural key, when the reference names its target that way. */
|
|
232
|
+
_targetNaturalKey: string | null;
|
|
233
|
+
/**
|
|
234
|
+
* The resolved target, over the project's `Record` union — every model in the
|
|
235
|
+
* project. Left as a type parameter so the generated file can name that
|
|
236
|
+
* union; the default is the honest answer for a consumer who has not narrowed
|
|
237
|
+
* it.
|
|
238
|
+
*/
|
|
239
|
+
record: TRecord | null;
|
|
240
|
+
/** A stored SPELLING of the model. Read as an input to `_targetModelKey`. */
|
|
125
241
|
_schema: string | null;
|
|
126
242
|
naturalKey: string | null;
|
|
127
243
|
_preview: FoirJsonValue | null;
|
|
@@ -153,69 +269,54 @@ export interface CollabInfo {
|
|
|
153
269
|
roomName: string;
|
|
154
270
|
}
|
|
155
271
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* own selection set for every union it expands, and it is the only field that
|
|
161
|
-
* cannot be `omit`ed (no omit path can name it). `_type` is the foir block-type
|
|
162
|
-
* token — the model key for a model-derived member, the lowercase primitive
|
|
163
|
-
* token otherwise — and is deliberately NOT protected from `omit` by the
|
|
164
|
-
* server, so a caller who omits it loses the second discriminant while keeping
|
|
165
|
-
* the first.
|
|
166
|
-
*/
|
|
167
|
-
export interface FoirBlockMeta<TType extends string, TTypename extends string> {
|
|
168
|
-
__typename: TTypename;
|
|
169
|
-
_type: TType;
|
|
170
|
-
_id: string | null;
|
|
171
|
-
_key: string | null;
|
|
172
|
-
_label: string | null;
|
|
173
|
-
}
|
|
174
|
-
export interface RichtextBlock extends FoirBlockMeta<'richtext', 'RichtextBlock'>, RichtextValue {
|
|
175
|
-
}
|
|
176
|
-
export interface ImageBlock extends FoirBlockMeta<'image', 'ImageBlock'>, Omit<ImageValue, 'url'> {
|
|
177
|
-
/**
|
|
178
|
-
* Nullable here, `String!` on `ImageValue`. Wrapping a value type as a block
|
|
179
|
-
* drops NonNull (`wrapValueFieldsAsBlock`), and reporting it non-null would
|
|
180
|
-
* be a lie a consumer's generated types cannot recover from.
|
|
181
|
-
*/
|
|
182
|
-
url: string | null;
|
|
183
|
-
}
|
|
184
|
-
export interface VideoBlock extends FoirBlockMeta<'video', 'VideoBlock'>, Omit<VideoValue, 'url'> {
|
|
185
|
-
/** Nullable here, `String!` on `VideoValue` — see `ImageBlock.url`. */
|
|
186
|
-
url: string | null;
|
|
187
|
-
}
|
|
188
|
-
export interface FileBlock extends FoirBlockMeta<'file', 'FileBlock'>, FileValue {
|
|
189
|
-
}
|
|
190
|
-
export interface MediaBlock extends FoirBlockMeta<'media', 'MediaBlock'>, MediaValue {
|
|
191
|
-
}
|
|
192
|
-
export interface TextBlock extends FoirBlockMeta<'text', 'TextBlock'> {
|
|
193
|
-
value: string | null;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* A reference to another record.
|
|
272
|
+
* `Image`, `Video`, `FileValue`, `Richtext`, `GeoPoint` and `Reference` above
|
|
273
|
+
* ARE the members. There is no separate item type, because an item is its
|
|
274
|
+
* value: `... on Image { url }` means the same thing inside a flexible field
|
|
275
|
+
* and at a plain `image` field, and one fragment reads it in both positions.
|
|
197
276
|
*
|
|
198
|
-
* `
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
* The
|
|
208
|
-
*
|
|
209
|
-
*
|
|
277
|
+
* `__typename` is optional on each, matching what graphql-codegen emits: it is
|
|
278
|
+
* present whenever selected, and the op compiler always selects it on a union's
|
|
279
|
+
* own selection set — it is the one field no `omit` path can name. Narrowing on
|
|
280
|
+
* it is exact regardless, because the literal types are disjoint.
|
|
281
|
+
*
|
|
282
|
+
* `_type` was the second discriminant and is gone with the envelope. It was
|
|
283
|
+
* never protected from `omit` anyway, so `__typename` was always the one to
|
|
284
|
+
* prefer.
|
|
285
|
+
*
|
|
286
|
+
* The three wrappers below have no replacement, because the things they
|
|
287
|
+
* described no longer exist:
|
|
288
|
+
*
|
|
289
|
+
* - `MediaBlock` — `media` stopped being a primitive at TTS-1391. It was
|
|
290
|
+
* never in the proto FieldType enum, and it is the one primitive name a
|
|
291
|
+
* project had also used as a model key.
|
|
292
|
+
* - `TextBlock` — TTS-1406 removed it. GraphQL requires a union member to be
|
|
293
|
+
* an object type and a text item's value is a bare scalar, which is the
|
|
294
|
+
* whole reason a wrapper existed. An inline model with a text field is how
|
|
295
|
+
* a text slot is authored.
|
|
296
|
+
* - `FlexibleBlock` — there is no fallback member. An item whose `_type`
|
|
297
|
+
* names nothing is nulled out of its list and reported, which is what a
|
|
298
|
+
* stored null already read as.
|
|
210
299
|
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
300
|
+
/** @deprecated Renamed to {@link Image}. The wrapper is gone; this IS the image. */
|
|
301
|
+
export type ImageBlock = Image;
|
|
302
|
+
/** @deprecated Renamed to {@link Video}. */
|
|
303
|
+
export type VideoBlock = Video;
|
|
304
|
+
/** @deprecated Renamed to {@link FileValue}. */
|
|
305
|
+
export type FileBlock = FileValue;
|
|
306
|
+
/** @deprecated Renamed to {@link Richtext}. */
|
|
307
|
+
export type RichtextBlock = Richtext;
|
|
308
|
+
/** @deprecated Renamed to {@link GeoPoint}. */
|
|
309
|
+
export type GeoPointValue = GeoPoint;
|
|
310
|
+
/** @deprecated Renamed to {@link Image}. */
|
|
311
|
+
export type ImageValue = Image;
|
|
312
|
+
/** @deprecated Renamed to {@link Video}. */
|
|
313
|
+
export type VideoValue = Video;
|
|
314
|
+
/** @deprecated Renamed to {@link Richtext}. */
|
|
315
|
+
export type RichtextValue = Richtext;
|
|
316
|
+
/** @deprecated Renamed to {@link Reference}. */
|
|
317
|
+
export type ReferenceValue<TRecord = FoirUnexpandedRecord> = Reference<TRecord>;
|
|
318
|
+
/** @deprecated Renamed to {@link Reference}. */
|
|
319
|
+
export type ReferenceBlock<TRecord = FoirUnexpandedRecord> = Reference<TRecord>;
|
|
219
320
|
/**
|
|
220
321
|
* What a nested union or a re-entered object resolves to.
|
|
221
322
|
*
|
|
@@ -225,11 +326,65 @@ export interface FlexibleBlock {
|
|
|
225
326
|
* `tilly_page.blocks → TillyPageBlock.blocks` cycle is reachable in two hops
|
|
226
327
|
* with no `include` and no caller input at all. At a degraded position the
|
|
227
328
|
* response carries `__typename` and nothing else, so that is what the generated
|
|
228
|
-
* type says.
|
|
329
|
+
* type says.
|
|
330
|
+
*
|
|
331
|
+
* # Reading past one
|
|
332
|
+
*
|
|
333
|
+
* A stopping point in front of a UNION can be spent a level on:
|
|
334
|
+
* `foir.product.findMany({ depth: 2 })` expands one more, and the response then
|
|
335
|
+
* carries that union's members here rather than `__typename` alone. A level
|
|
336
|
+
* costs one more expansion at each stopping point inside the expansion — so it
|
|
337
|
+
* compounds where there are several, and costs nothing per union MEMBER — and
|
|
338
|
+
* the call is refused client-side, with the arithmetic, when it would cross the
|
|
339
|
+
* server's field ceiling. See `FoirNamespaceCall.depth`.
|
|
340
|
+
*
|
|
341
|
+
* The TYPE follows the level. A generated composite on the path to a stopping
|
|
342
|
+
* point takes a `<D>` level parameter (see `FoirDepthLevel`), so at `depth: 2`
|
|
343
|
+
* the position resolves to the expanded union — `<Field>Blocks`, the type
|
|
344
|
+
* exported beside the `<Field>BlocksDegraded` named here — rather than to this
|
|
345
|
+
* one. The caller narrows on `__typename` and reads the member's own field; no
|
|
346
|
+
* cast, and no hand-written widening.
|
|
347
|
+
*
|
|
348
|
+
* `D` defaults to `1`, so a call passing no `depth` reaches THIS type at the
|
|
349
|
+
* stopping point exactly as it always did.
|
|
350
|
+
*
|
|
351
|
+
* A stopping point that is a composite CYCLE rather than a union — `menu.items
|
|
352
|
+
* .children` — has no union to expand and stays `__typename` at every depth.
|
|
229
353
|
*/
|
|
230
354
|
export interface FoirDegraded<TTypename extends string = string> {
|
|
231
355
|
__typename: TTypename;
|
|
232
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* The union levels the generated types describe — the type-level half of
|
|
359
|
+
* `depth`.
|
|
360
|
+
*
|
|
361
|
+
* A generated composite on the path to a stopping point takes one of these as
|
|
362
|
+
* a parameter, defaulted to `1`, and the model's shape at each level is named
|
|
363
|
+
* under `FoirModelDefinition.atDepth`. `1` is the complete-by-default document
|
|
364
|
+
* and is what every existing reference to a generated interface resolves to,
|
|
365
|
+
* which is why adding the parameter changed no result type.
|
|
366
|
+
*
|
|
367
|
+
* Four because depth is a budget against the server's 10,000-field ceiling and
|
|
368
|
+
* four is past what a generated module usefully describes: on the live dev
|
|
369
|
+
* project `product.findUnique` measures 318 fields at the default, 468 at 2 and
|
|
370
|
+
* 618 at 3. Those levels all fit since TTS-1448 — they read 1,203 / 4,308 /
|
|
371
|
+
* 13,623 when a union position was charged for every member — so the bound here
|
|
372
|
+
* is about how much generated type surface is worth emitting, not about what
|
|
373
|
+
* the server will run. A call
|
|
374
|
+
* asking for more is not an error: `atDepth` simply has no entry, the result
|
|
375
|
+
* falls back to the default shape, and the caller narrows by hand exactly as
|
|
376
|
+
* they did before. Under-promising is the safe direction, and the wire is
|
|
377
|
+
* unaffected — the printer's budget is a runtime number with no cap here.
|
|
378
|
+
*/
|
|
379
|
+
export type FoirDepthLevel = 1 | 2 | 3 | 4;
|
|
380
|
+
/**
|
|
381
|
+
* `FoirDepthBelow[3] === 2` — one union level spent.
|
|
382
|
+
*
|
|
383
|
+
* Mirrors the printer's `depth - 1` at an expanded stopping point
|
|
384
|
+
* (`document.ts`, `printFields`), and lives beside `FoirDepthLevel` so the two
|
|
385
|
+
* cannot disagree about how many levels exist.
|
|
386
|
+
*/
|
|
387
|
+
export type FoirDepthBelow = [never, never, 1, 2, 3];
|
|
233
388
|
/** A `Record`-union value the compiler did not expand. See `FoirDegraded`. */
|
|
234
389
|
export type FoirUnexpandedRecord = FoirDegraded;
|
|
235
390
|
/**
|
|
@@ -273,6 +428,128 @@ export interface FoirUpdateManyPayload {
|
|
|
273
428
|
count: number;
|
|
274
429
|
ids: string[];
|
|
275
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* What a note is ABOUT — the closed set the platform's write path enforces.
|
|
433
|
+
*
|
|
434
|
+
* On the wire it is `String!`, not a GraphQL enum, so the manifest publishes no
|
|
435
|
+
* `enumValues` for it and `foir types` cannot generate this union. It is here
|
|
436
|
+
* for the same reason the value objects are: platform-owned, identical in every
|
|
437
|
+
* project, and otherwise hand-written once per consumer.
|
|
438
|
+
*
|
|
439
|
+
* It is never a MODEL KEY. Model keys are the project's to choose, so a project
|
|
440
|
+
* with a model keyed `file` would make one value mean two things; a note on a
|
|
441
|
+
* record is `'record'` plus the model key on `subjectModelKey`.
|
|
442
|
+
*
|
|
443
|
+
* This mirrors a platform-side set, and the obligation that comes with a mirror
|
|
444
|
+
* (see the file header) applies: a kind added there widens this union in a
|
|
445
|
+
* minor release, and until then a value outside it is a row no writer could
|
|
446
|
+
* have produced.
|
|
447
|
+
*/
|
|
448
|
+
export type FoirNoteSubjectType = 'record' | 'file' | 'model' | 'operation' | 'schedule' | 'customer';
|
|
449
|
+
/**
|
|
450
|
+
* One file the customer submitted with their note.
|
|
451
|
+
*
|
|
452
|
+
* The file's own facts, and nothing about the platform's handling of it: when
|
|
453
|
+
* the link row was written and which retention clock it starts are not the
|
|
454
|
+
* author's business. What is here is enough to render "you sent this".
|
|
455
|
+
*/
|
|
456
|
+
export interface FoirCustomerNoteAttachment {
|
|
457
|
+
/** The file's id — the same one `createMyNote` was given. */
|
|
458
|
+
fileId: string;
|
|
459
|
+
filename: string;
|
|
460
|
+
mimeType: string;
|
|
461
|
+
/** Size in bytes, as stored. Authoritative; not the number the uploader declared. */
|
|
462
|
+
size: number;
|
|
463
|
+
url: string;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* One note on the customer plane — `foir.ns.notes.myNotes` and
|
|
467
|
+
* `foir.ns.notes.createMyNote`.
|
|
468
|
+
*
|
|
469
|
+
* Deliberately narrower than the note your team sees in the dashboard. There is
|
|
470
|
+
* no visibility, no resolution note, no mentions and no metadata: those are the
|
|
471
|
+
* project's view of a thread, not the author's, and the customer-facing type
|
|
472
|
+
* does not merely omit them from the document — the surface does not carry them.
|
|
473
|
+
*/
|
|
474
|
+
export interface FoirCustomerNote {
|
|
475
|
+
id: string;
|
|
476
|
+
/** The note's prose. */
|
|
477
|
+
body: string | null;
|
|
478
|
+
subjectType: FoirNoteSubjectType;
|
|
479
|
+
subjectId: string;
|
|
480
|
+
/** The record's model key. Present only on a `record` subject. */
|
|
481
|
+
subjectModelKey: string | null;
|
|
482
|
+
/** Set when this note is a reply within a thread. */
|
|
483
|
+
parentNoteId: string | null;
|
|
484
|
+
threadRootId: string | null;
|
|
485
|
+
isResolved: boolean;
|
|
486
|
+
/**
|
|
487
|
+
* The files submitted with this note. Empty when there are none.
|
|
488
|
+
*
|
|
489
|
+
* The one place the customer surface is WIDER than "the author's own prose",
|
|
490
|
+
* and deliberately: an author who attached a screenshot has to be able to see
|
|
491
|
+
* that it arrived, or the only readings left to them are that it failed
|
|
492
|
+
* silently or that it was taken away.
|
|
493
|
+
*/
|
|
494
|
+
attachments: FoirCustomerNoteAttachment[];
|
|
495
|
+
/** ISO-8601. */
|
|
496
|
+
createdAt: string;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* What a note surface has to know about the project before it renders anything
|
|
500
|
+
* — `foir.ns.notes.noteConfig`.
|
|
501
|
+
*
|
|
502
|
+
* Charged `notes:write` rather than `notes:read`, and refused to a caller with
|
|
503
|
+
* no customer session, because the only caller it is useful to is one that can
|
|
504
|
+
* submit. So a composer can read it as its single readiness probe: an answer
|
|
505
|
+
* means this visitor may write, and a refusal names which half is missing.
|
|
506
|
+
*/
|
|
507
|
+
export interface FoirNoteConfig {
|
|
508
|
+
/**
|
|
509
|
+
* Whether this project's note surfaces may OFFER to capture a screenshot.
|
|
510
|
+
*
|
|
511
|
+
* It gates the offer, not the storing. Capture stays opt-in per submission —
|
|
512
|
+
* the browser's own picker is the consent gate and it cannot be bypassed.
|
|
513
|
+
*/
|
|
514
|
+
screenshotsEnabled: boolean;
|
|
515
|
+
}
|
|
516
|
+
/** `myNotes` arguments. Forward-only cursor pagination, like every list read. */
|
|
517
|
+
export interface FoirMyNotesArgs {
|
|
518
|
+
first?: number;
|
|
519
|
+
after?: string;
|
|
520
|
+
/** Narrow to one kind of subject. */
|
|
521
|
+
subjectType?: FoirNoteSubjectType;
|
|
522
|
+
/** Narrow to one subject — a record id, a file id, a model key. */
|
|
523
|
+
subjectId?: string;
|
|
524
|
+
/** Read one thread. Returns only the notes in it this caller can see. */
|
|
525
|
+
threadRootId?: string;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* `myNotes` — the notes this customer wrote, plus the replies your team
|
|
529
|
+
* deliberately sent them. Never another customer's, and never an operator's
|
|
530
|
+
* internal ones.
|
|
531
|
+
*/
|
|
532
|
+
export type FoirMyNotesResult = FoirConnection<FoirCustomerNote>;
|
|
533
|
+
/** `createMyNote` arguments. */
|
|
534
|
+
export interface FoirCreateMyNoteArgs {
|
|
535
|
+
subjectType: FoirNoteSubjectType;
|
|
536
|
+
subjectId: string;
|
|
537
|
+
/** Required when `subjectType` is `'record'`, refused otherwise. */
|
|
538
|
+
subjectModelKey?: string;
|
|
539
|
+
body: string;
|
|
540
|
+
/** Reply within an existing thread. */
|
|
541
|
+
parentNoteId?: string;
|
|
542
|
+
/**
|
|
543
|
+
* Files to submit with this note, already uploaded through
|
|
544
|
+
* `createFileUpload` / `confirmFileUpload`.
|
|
545
|
+
*
|
|
546
|
+
* A file this caller cannot read is REFUSED and the note is not written. That
|
|
547
|
+
* is not a rough edge to code around: a create that accepted the note and
|
|
548
|
+
* dropped the attachment would leave the author believing they sent a
|
|
549
|
+
* screenshot nobody has.
|
|
550
|
+
*/
|
|
551
|
+
attachmentFileIds?: string[];
|
|
552
|
+
}
|
|
276
553
|
export type FoirDeviceType = 'DESKTOP' | 'MOBILE' | 'TABLET';
|
|
277
554
|
export type FoirPlatformType = 'IOS' | 'ANDROID' | 'WEB';
|
|
278
555
|
/**
|