@segmentstream/app 0.0.0-stage → 0.38.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/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +1236 -2
- package/dist/agent.d.ts +56 -0
- package/dist/agent.js +203 -0
- package/dist/app.d.ts +82 -0
- package/dist/app.js +434 -0
- package/dist/browser-auth-capability.d.ts +2 -0
- package/dist/browser-auth-capability.js +2 -0
- package/dist/browser-revision.d.ts +19 -0
- package/dist/browser-revision.js +140 -0
- package/dist/channel-protocol.d.ts +16 -0
- package/dist/channel-protocol.js +17 -0
- package/dist/channel-session.d.ts +22 -0
- package/dist/channel-session.js +89 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.js +112 -0
- package/dist/context.d.ts +10 -0
- package/dist/context.js +1 -0
- package/dist/cookies.d.ts +56 -0
- package/dist/cookies.js +131 -0
- package/dist/data.d.ts +233 -0
- package/dist/data.js +206 -0
- package/dist/decision-pages.d.ts +14 -0
- package/dist/decision-pages.js +87 -0
- package/dist/deployment.d.ts +30 -0
- package/dist/deployment.js +72 -0
- package/dist/errors.d.ts +60 -0
- package/dist/errors.js +123 -0
- package/dist/federation.d.ts +24 -0
- package/dist/federation.js +613 -0
- package/dist/groups.d.ts +95 -0
- package/dist/groups.js +280 -0
- package/dist/handlers.d.ts +10 -0
- package/dist/handlers.js +161 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +29 -0
- package/dist/jobs.d.ts +49 -0
- package/dist/jobs.js +40 -0
- package/dist/legacy.d.ts +77 -0
- package/dist/legacy.js +57 -0
- package/dist/logo.d.ts +1 -0
- package/dist/logo.js +25 -0
- package/dist/me.d.ts +42 -0
- package/dist/me.js +54 -0
- package/dist/navigation/build.d.ts +68 -0
- package/dist/navigation/build.js +290 -0
- package/dist/navigation/cli.d.ts +19 -0
- package/dist/navigation/cli.js +37 -0
- package/dist/navigation/generate.d.ts +43 -0
- package/dist/navigation/generate.js +138 -0
- package/dist/navigation/next.d.ts +10 -0
- package/dist/navigation/next.js +18 -0
- package/dist/navigation-protocol.d.ts +55 -0
- package/dist/navigation-protocol.js +298 -0
- package/dist/neon.d.ts +101 -0
- package/dist/neon.js +539 -0
- package/dist/oauth-completion.d.ts +6 -0
- package/dist/oauth-completion.js +106 -0
- package/dist/oauth.d.ts +59 -0
- package/dist/oauth.js +129 -0
- package/dist/ontology-names.d.ts +10 -0
- package/dist/ontology-names.js +38 -0
- package/dist/ontology-transport.d.ts +34 -0
- package/dist/ontology-transport.js +130 -0
- package/dist/ontology-wire.d.ts +66 -0
- package/dist/ontology-wire.js +355 -0
- package/dist/ontology.d.ts +381 -0
- package/dist/ontology.js +367 -0
- package/dist/pages.d.ts +6 -0
- package/dist/pages.js +6 -0
- package/dist/parameters.d.ts +55 -0
- package/dist/parameters.js +118 -0
- package/dist/permissions.d.ts +19 -0
- package/dist/permissions.js +55 -0
- package/dist/pkce.d.ts +8 -0
- package/dist/pkce.js +40 -0
- package/dist/proxy.d.ts +25 -0
- package/dist/proxy.js +135 -0
- package/dist/request-timing.d.ts +6 -0
- package/dist/request-timing.js +53 -0
- package/dist/return-to.d.ts +2 -0
- package/dist/return-to.js +24 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +80 -0
- package/dist/sessions.d.ts +27 -0
- package/dist/sessions.js +72 -0
- package/dist/sign-in.d.ts +37 -0
- package/dist/sign-in.js +95 -0
- package/dist/storage.d.ts +79 -0
- package/dist/storage.js +180 -0
- package/dist/telegram-launch.d.ts +7 -0
- package/dist/telegram-launch.js +134 -0
- package/dist/telegram.d.ts +2 -0
- package/dist/telegram.js +6 -0
- package/dist/tokens.d.ts +51 -0
- package/dist/tokens.js +70 -0
- package/dist/ui/agent-connect.d.ts +18 -0
- package/dist/ui/agent-connect.js +23 -0
- package/dist/ui/components.d.ts +27 -0
- package/dist/ui/components.js +71 -0
- package/dist/ui/hooks.d.ts +19 -0
- package/dist/ui/hooks.js +56 -0
- package/dist/ui/index.d.ts +22 -0
- package/dist/ui/index.js +15 -0
- package/dist/ui/navigation.d.ts +5 -0
- package/dist/ui/navigation.js +8 -0
- package/dist/ui/segmentstream-logo.d.ts +2 -0
- package/dist/ui/segmentstream-logo.js +7 -0
- package/dist/ui/sign-in-check.d.ts +14 -0
- package/dist/ui/sign-in-check.js +41 -0
- package/dist/ui/sign-in.d.ts +17 -0
- package/dist/ui/sign-in.js +65 -0
- package/dist/ui/store.d.ts +80 -0
- package/dist/ui/store.js +280 -0
- package/dist/ui/styles.css +249 -0
- package/dist/ui/telegram-sign-in.d.ts +16 -0
- package/dist/ui/telegram-sign-in.js +21 -0
- package/dist/ui/use-browser-sign-in.d.ts +52 -0
- package/dist/ui/use-browser-sign-in.js +169 -0
- package/dist/ui/use-channel-sign-in.d.ts +10 -0
- package/dist/ui/use-channel-sign-in.js +118 -0
- package/dist/ui/use-sign-in.d.ts +109 -0
- package/dist/ui/use-sign-in.js +304 -0
- package/package.json +95 -4
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import type { EntityMetricQuery, MetricQuery, MetricQueryResult } from "./data.js";
|
|
2
|
+
import { type EarlierEntityQueryMetricsName, type EarlierMetricsOf, type EarlierModelMetricsOf, type EarlierQueryMetricsName } from "./legacy.js";
|
|
3
|
+
import type { FileDownloadOptions, FileRevision, FileTransfer } from "./storage.js";
|
|
4
|
+
/**
|
|
5
|
+
* The typed client for the app's ontology service, `/api/ontology`. The app imports its ontology as
|
|
6
|
+
* types only (`import type ontology from "../../ontology"`) and passes `typeof ontology` to
|
|
7
|
+
* `createSegmentStreamApp`; entity records, action inputs and action results are read from the
|
|
8
|
+
* ontology SDK's `Ontology`, `Entity` and `Action` types. The types are read structurally, so the
|
|
9
|
+
* app needs neither the ontology SDK nor Effect at runtime, and `app/` and `ontology/` may install
|
|
10
|
+
* their own copies.
|
|
11
|
+
*/
|
|
12
|
+
/** JSON as the ontology service sends and accepts it. */
|
|
13
|
+
export type JsonValue = string | number | boolean | null | ReadonlyArray<JsonValue> | {
|
|
14
|
+
readonly [key: string]: JsonValue;
|
|
15
|
+
};
|
|
16
|
+
/** A record of an entity the client has no types for. */
|
|
17
|
+
export type JsonRecord = {
|
|
18
|
+
readonly [field: string]: JsonValue;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Conditions on one field; all of them must hold. `contains` and `startsWith` ignore case;
|
|
22
|
+
* `between` includes both ends; `has` and `hasAny` match a list, such as `user.roles`, that holds
|
|
23
|
+
* the value or any of the values. In a `where`, a bare value stands for `{ eq: value }`.
|
|
24
|
+
*/
|
|
25
|
+
export interface FieldFilter {
|
|
26
|
+
readonly eq?: JsonValue;
|
|
27
|
+
readonly ne?: JsonValue;
|
|
28
|
+
readonly in?: ReadonlyArray<JsonValue>;
|
|
29
|
+
readonly isNull?: boolean;
|
|
30
|
+
readonly contains?: string;
|
|
31
|
+
readonly startsWith?: string;
|
|
32
|
+
readonly gt?: number | string;
|
|
33
|
+
readonly gte?: number | string;
|
|
34
|
+
readonly lt?: number | string;
|
|
35
|
+
readonly lte?: number | string;
|
|
36
|
+
readonly between?: readonly [number | string, number | string];
|
|
37
|
+
readonly has?: string;
|
|
38
|
+
readonly hasAny?: ReadonlyArray<string>;
|
|
39
|
+
}
|
|
40
|
+
/** A filter on a to-many relationship: some, none or every related record matches. */
|
|
41
|
+
export interface ManyFilter {
|
|
42
|
+
readonly some?: Where;
|
|
43
|
+
readonly none?: Where;
|
|
44
|
+
readonly every?: Where;
|
|
45
|
+
}
|
|
46
|
+
/** Conditions on a record by field or relationship name, with `and`, `or` and `not`. */
|
|
47
|
+
export interface Where {
|
|
48
|
+
readonly and?: ReadonlyArray<Where>;
|
|
49
|
+
readonly or?: ReadonlyArray<Where>;
|
|
50
|
+
readonly not?: Where;
|
|
51
|
+
readonly [field: string]: FieldFilter | ManyFilter | Where | ReadonlyArray<Where> | JsonValue | undefined;
|
|
52
|
+
}
|
|
53
|
+
export interface OrderBy<Field extends string = string> {
|
|
54
|
+
readonly field: Field;
|
|
55
|
+
readonly direction?: "asc" | "desc";
|
|
56
|
+
}
|
|
57
|
+
/** A query: the same language for `find` (as URL parameters) and `query` (as a JSON body). */
|
|
58
|
+
export interface OntologyQuery<Row = JsonRecord, Selection extends readonly (keyof Row & string)[] | undefined = undefined> {
|
|
59
|
+
/** Base fields to return. The id and requested relationships are always returned. */
|
|
60
|
+
readonly select?: Selection;
|
|
61
|
+
readonly where?: Where;
|
|
62
|
+
readonly orderBy?: ReadonlyArray<OrderBy<keyof Row & string>>;
|
|
63
|
+
/**
|
|
64
|
+
* Related records to add to each record, by relationship name: `["owner"]` or `{ owner: true }`.
|
|
65
|
+
*/
|
|
66
|
+
readonly include?: ReadonlyArray<string> | {
|
|
67
|
+
readonly [relationship: string]: true;
|
|
68
|
+
};
|
|
69
|
+
/** The `nextCursor` of the previous page. */
|
|
70
|
+
readonly after?: string;
|
|
71
|
+
/** Records per page, 50 by default and at most 200. */
|
|
72
|
+
readonly limit?: number;
|
|
73
|
+
}
|
|
74
|
+
/** A page of records. `nextCursor` is `null` on the last page. */
|
|
75
|
+
export interface OntologyPage<Row> {
|
|
76
|
+
readonly items: ReadonlyArray<Row>;
|
|
77
|
+
readonly nextCursor: string | null;
|
|
78
|
+
readonly projected?: true;
|
|
79
|
+
}
|
|
80
|
+
/** Selected fields are required; other fields may be absent. Dynamic lists promise only id. */
|
|
81
|
+
export type SelectedRecord<Row, Selection extends readonly string[] | undefined> = Selection extends readonly string[] ? Partial<Row> & (number extends Selection["length"] ? object : Pick<Row, Extract<Selection[number], keyof Row>>) & {
|
|
82
|
+
readonly id: string;
|
|
83
|
+
} : Row;
|
|
84
|
+
type ReadQuery = OntologyQuery<JsonRecord, readonly string[] | undefined>;
|
|
85
|
+
export type EditKind = "create" | "update" | "delete" | "link" | "unlink";
|
|
86
|
+
export interface Change {
|
|
87
|
+
readonly before: JsonValue;
|
|
88
|
+
readonly after: JsonValue;
|
|
89
|
+
}
|
|
90
|
+
/** What one action changed on one record. */
|
|
91
|
+
export interface Edit {
|
|
92
|
+
readonly entity: string;
|
|
93
|
+
readonly id: string;
|
|
94
|
+
readonly kind: EditKind;
|
|
95
|
+
readonly changes: {
|
|
96
|
+
readonly [field: string]: Change;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export interface HistoryEntry {
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly recordId: string;
|
|
102
|
+
/** The qualified action, for example `lead.changeStatus`. */
|
|
103
|
+
readonly action: string;
|
|
104
|
+
/** Shared by every entry one run of an action wrote. */
|
|
105
|
+
readonly actionId: string;
|
|
106
|
+
readonly kind: EditKind;
|
|
107
|
+
/** The user who ran the action; `null` when the platform wrote. */
|
|
108
|
+
readonly principalId: string | null;
|
|
109
|
+
readonly at: string;
|
|
110
|
+
readonly changes: {
|
|
111
|
+
readonly [field: string]: Change;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export interface HistoryPage {
|
|
115
|
+
readonly items: ReadonlyArray<HistoryEntry>;
|
|
116
|
+
readonly nextCursor: string | null;
|
|
117
|
+
}
|
|
118
|
+
export interface ValidationIssue {
|
|
119
|
+
readonly path: ReadonlyArray<string | number>;
|
|
120
|
+
readonly message: string;
|
|
121
|
+
}
|
|
122
|
+
/** `POST /api/ontology/<entity>/actions/<action>` answers `{ result, validation, edits }`. */
|
|
123
|
+
export interface ActionResponse<Result = unknown> {
|
|
124
|
+
/** What the action returned; `null` under `validateOnly` and for actions without a result. */
|
|
125
|
+
readonly result: Result | null;
|
|
126
|
+
readonly validation: {
|
|
127
|
+
readonly ok: boolean;
|
|
128
|
+
readonly issues: ReadonlyArray<ValidationIssue>;
|
|
129
|
+
};
|
|
130
|
+
/** The records the action changed, as their history records each change. */
|
|
131
|
+
readonly edits: ReadonlyArray<Edit>;
|
|
132
|
+
}
|
|
133
|
+
export interface RequestOptions {
|
|
134
|
+
readonly signal?: AbortSignal;
|
|
135
|
+
}
|
|
136
|
+
export interface ActionOptions extends RequestOptions {
|
|
137
|
+
/** Validate the input and report issues in `validation` without a write. */
|
|
138
|
+
readonly validateOnly?: boolean;
|
|
139
|
+
readonly idempotencyKey?: string;
|
|
140
|
+
readonly createIntent?: string;
|
|
141
|
+
}
|
|
142
|
+
export interface HistoryOptions extends RequestOptions {
|
|
143
|
+
readonly after?: string;
|
|
144
|
+
/** Entries per page, at most 200. */
|
|
145
|
+
readonly limit?: number;
|
|
146
|
+
}
|
|
147
|
+
/** Runs one action: `lead.actions.changeStatus({ lead, status }, { validateOnly })`. */
|
|
148
|
+
export type ActionCall<Input, Result> = (input: Input, options?: ActionOptions) => Promise<ActionResponse<Result>>;
|
|
149
|
+
/** The generated actions every entity has; their inputs are not typed by the client. */
|
|
150
|
+
export interface GeneratedActions {
|
|
151
|
+
readonly create: ActionCall<JsonRecord, JsonValue>;
|
|
152
|
+
readonly update: ActionCall<{
|
|
153
|
+
readonly id: string;
|
|
154
|
+
} & JsonRecord, JsonValue>;
|
|
155
|
+
readonly delete: ActionCall<{
|
|
156
|
+
readonly id: string;
|
|
157
|
+
}, JsonValue>;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The generated actions of the built-in `user`, which change a member's roles and activation. Role
|
|
161
|
+
* names are spelled as `requireUser().roles` spells them. Each returns the updated record.
|
|
162
|
+
*/
|
|
163
|
+
export interface UserGeneratedActions<Row = JsonRecord> {
|
|
164
|
+
readonly invite: ActionCall<{
|
|
165
|
+
readonly email: string;
|
|
166
|
+
readonly name?: string;
|
|
167
|
+
readonly roles?: ReadonlyArray<string>;
|
|
168
|
+
}, Row>;
|
|
169
|
+
readonly grantRoles: ActionCall<{
|
|
170
|
+
readonly id: string;
|
|
171
|
+
readonly roles: ReadonlyArray<string>;
|
|
172
|
+
}, Row>;
|
|
173
|
+
readonly revokeRoles: ActionCall<{
|
|
174
|
+
readonly id: string;
|
|
175
|
+
readonly roles: ReadonlyArray<string>;
|
|
176
|
+
} | {
|
|
177
|
+
readonly id: string;
|
|
178
|
+
readonly all: true;
|
|
179
|
+
}, Row>;
|
|
180
|
+
readonly deactivate: ActionCall<{
|
|
181
|
+
readonly id: string;
|
|
182
|
+
}, Row>;
|
|
183
|
+
readonly reactivate: ActionCall<{
|
|
184
|
+
readonly id: string;
|
|
185
|
+
}, Row>;
|
|
186
|
+
}
|
|
187
|
+
type BlobPropertyNames<Row> = string extends keyof Row ? string : {
|
|
188
|
+
[K in keyof Row]-?: [NonNullable<Row[K]>] extends [never] ? never : NonNullable<Row[K]> extends FileRevision ? K : never;
|
|
189
|
+
}[keyof Row] & string;
|
|
190
|
+
export interface EntityFilesClient<Property extends string = string> {
|
|
191
|
+
/**
|
|
192
|
+
* A short-lived GET grant for a blob property, authorized as the signed-in member.
|
|
193
|
+
* The ontology checks current read permission and record scopes before issuing the grant.
|
|
194
|
+
* File bytes are read from the grant's URL, outside ontology JSON responses.
|
|
195
|
+
*/
|
|
196
|
+
readonly download: (id: string, property: Property, options?: FileDownloadOptions) => Promise<FileTransfer>;
|
|
197
|
+
}
|
|
198
|
+
export interface EntityClient<Row, Actions, Generated = GeneratedActions> {
|
|
199
|
+
/** `GET /api/ontology/<entity>`: filter, sort and page through records. */
|
|
200
|
+
readonly find: <const Selection extends readonly (keyof Row & string)[] | undefined = undefined>(query?: OntologyQuery<Row, Selection>, options?: RequestOptions) => Promise<OntologyPage<SelectedRecord<Row, Selection>>>;
|
|
201
|
+
/** `POST /api/ontology/<entity>/query`: the same query as a JSON body. */
|
|
202
|
+
readonly query: <const Selection extends readonly (keyof Row & string)[] | undefined = undefined>(query?: OntologyQuery<Row, Selection>, options?: RequestOptions) => Promise<OntologyPage<SelectedRecord<Row, Selection>>>;
|
|
203
|
+
/** `GET /api/ontology/<entity>/<id>`. */
|
|
204
|
+
readonly get: (id: string, options?: RequestOptions) => Promise<Row>;
|
|
205
|
+
/** `GET /api/ontology/<entity>/<id>/history`: what each action changed, newest first. */
|
|
206
|
+
readonly history: (id: string, options?: HistoryOptions) => Promise<HistoryPage>;
|
|
207
|
+
/** Read the entity's blob properties as the signed-in member. */
|
|
208
|
+
readonly files: EntityFilesClient<BlobPropertyNames<Row>>;
|
|
209
|
+
/**
|
|
210
|
+
* The entity's actions by name, authored and generated. An entity that declares
|
|
211
|
+
* `writes: "actions"` has no generated `create`, `update` or `delete`.
|
|
212
|
+
*/
|
|
213
|
+
readonly actions: Actions & Generated;
|
|
214
|
+
/** Any action by name, for generated actions such as `upsertByEmail`, `link` and `unlink`. */
|
|
215
|
+
readonly action: (name: string, input: JsonRecord, options?: ActionOptions) => Promise<ActionResponse<JsonValue>>;
|
|
216
|
+
}
|
|
217
|
+
type EntitiesOf<O> = O extends {
|
|
218
|
+
readonly config: {
|
|
219
|
+
readonly entities: ReadonlyArray<infer E>;
|
|
220
|
+
};
|
|
221
|
+
} ? E : never;
|
|
222
|
+
type NameOf<E> = E extends {
|
|
223
|
+
readonly name: infer N extends string;
|
|
224
|
+
} ? N : never;
|
|
225
|
+
type RecordOf<E> = E extends {
|
|
226
|
+
readonly Type: infer T;
|
|
227
|
+
} ? T : JsonRecord;
|
|
228
|
+
type ActionsOf<E> = E extends {
|
|
229
|
+
readonly actions: infer A;
|
|
230
|
+
} ? A : never;
|
|
231
|
+
/** The generated writes of an entity: none when it declares `writes: "actions"`. */
|
|
232
|
+
type GeneratedOf<E> = E extends {
|
|
233
|
+
readonly "~ontology.writes": infer W;
|
|
234
|
+
} ? [W] extends ["actions"] ? unknown : GeneratedActions : GeneratedActions;
|
|
235
|
+
type InputOf<A> = A extends {
|
|
236
|
+
readonly input: {
|
|
237
|
+
readonly Encoded: infer I;
|
|
238
|
+
};
|
|
239
|
+
} ? I : JsonRecord;
|
|
240
|
+
/** An Effect yields its success when iterated, as `yield*` in `Effect.gen` does. */
|
|
241
|
+
type SuccessOf<F> = F extends {
|
|
242
|
+
[Symbol.iterator](): {
|
|
243
|
+
next(...args: ReadonlyArray<any>): IteratorResult<unknown, infer R>;
|
|
244
|
+
};
|
|
245
|
+
} ? R : unknown;
|
|
246
|
+
/** Actions without a result answer `result: null`. */
|
|
247
|
+
type JsonResult<R> = [R] extends [void] ? null : R;
|
|
248
|
+
type ResultOf<A> = A extends {
|
|
249
|
+
handler(context: never): infer F;
|
|
250
|
+
} ? JsonResult<SuccessOf<F>> : unknown;
|
|
251
|
+
type ActionClients<A> = {
|
|
252
|
+
readonly [K in keyof A & string]: ActionCall<InputOf<A[K]>, ResultOf<A[K]>>;
|
|
253
|
+
};
|
|
254
|
+
type PropertiesOf<E> = E extends {
|
|
255
|
+
readonly properties: infer P;
|
|
256
|
+
} ? P : never;
|
|
257
|
+
/** Declared names only: a definition typed as any `Metrics` names none the client can check. */
|
|
258
|
+
export type DeclaredNames<M> = string extends keyof M ? never : keyof M & string;
|
|
259
|
+
/**
|
|
260
|
+
* A warehouse-backed entity's `metrics`, or the metrics of a stored entity's definition. An
|
|
261
|
+
* ontology SDK before manifest version 14 declares them under their earlier name, which
|
|
262
|
+
* `EarlierMetricsOf` reads.
|
|
263
|
+
*/
|
|
264
|
+
type MetricsOf<E> = (E extends {
|
|
265
|
+
readonly metrics: infer M;
|
|
266
|
+
} ? keyof M & string : E extends {
|
|
267
|
+
readonly definition: {
|
|
268
|
+
readonly metrics?: infer M;
|
|
269
|
+
};
|
|
270
|
+
} ? DeclaredNames<NonNullable<M>> : never) | EarlierMetricsOf<E>;
|
|
271
|
+
type RelationshipsOf<E> = E extends {
|
|
272
|
+
readonly relationships: infer R;
|
|
273
|
+
} ? R : never;
|
|
274
|
+
type IsWarehouseBacked<E> = E extends {
|
|
275
|
+
readonly definition: {
|
|
276
|
+
readonly source: object;
|
|
277
|
+
};
|
|
278
|
+
} ? true : false;
|
|
279
|
+
/**
|
|
280
|
+
* A `rel.one`, which metric queries may follow. Every relationship of a warehouse-backed entity is
|
|
281
|
+
* matched by value; a stored entity's may also be keyed (`<relationship>_id` joined to `id`).
|
|
282
|
+
*/
|
|
283
|
+
interface ToOne {
|
|
284
|
+
readonly cardinality: "one";
|
|
285
|
+
}
|
|
286
|
+
/** The target's name, or `string` when a thunk erased it or the ontology SDK predates the name. */
|
|
287
|
+
type TargetNameOf<R> = R extends {
|
|
288
|
+
readonly "~ontology.target": infer Name extends string;
|
|
289
|
+
} ? Name : string;
|
|
290
|
+
/** The entity of `O` named `Name`. `User` is not replicated, so metric queries never reach it. */
|
|
291
|
+
type EntityNamed<O, Name extends string> = Name extends "user" ? never : Extract<EntitiesOf<O>, {
|
|
292
|
+
readonly name: Name;
|
|
293
|
+
}>;
|
|
294
|
+
/** Properties whose values are scalars. json and blob values are objects, which queries skip. */
|
|
295
|
+
type ScalarPropertiesOf<T> = {
|
|
296
|
+
[K in keyof PropertiesOf<T>]-?: PropertiesOf<T>[K] extends {
|
|
297
|
+
readonly Type: infer V;
|
|
298
|
+
} ? [Extract<V, object>] extends [never] ? K : never : K;
|
|
299
|
+
}[keyof PropertiesOf<T>] & string;
|
|
300
|
+
/** What a path may end on: the target's scalar properties, and `id` when the target is stored. */
|
|
301
|
+
type FieldsOf<T> = ScalarPropertiesOf<T> | (IsWarehouseBacked<T> extends true ? never : "id");
|
|
302
|
+
/** The rest of a path after reaching `T`: a field, or one more relationship when `Again`. */
|
|
303
|
+
type PathEnds<T, O, Again extends boolean> = [T] extends [never] ? never : FieldsOf<T> | (Again extends true ? PathsFrom<T, O, false> : never);
|
|
304
|
+
type PathsFrom<E, O, Again extends boolean> = {
|
|
305
|
+
[K in keyof RelationshipsOf<E> & string]: RelationshipsOf<E>[K] extends ToOne ? string extends TargetNameOf<RelationshipsOf<E>[K]> ? `${K}.${string}` : `${K}.${PathEnds<EntityNamed<O, TargetNameOf<RelationshipsOf<E>[K]>>, O, Again>}` : never;
|
|
306
|
+
}[keyof RelationshipsOf<E> & string];
|
|
307
|
+
/**
|
|
308
|
+
* Related properties of `E` as metric query paths through at most two `rel.one` relationships:
|
|
309
|
+
* `product.brand`, `product.brand.name`. A thunk target erases its entity, so any path may follow
|
|
310
|
+
* its relationship: `` `${relationship}.${string}` ``.
|
|
311
|
+
*/
|
|
312
|
+
type PathsOf<E, O> = PathsFrom<E, O, true>;
|
|
313
|
+
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
314
|
+
/**
|
|
315
|
+
* A snake_case entity name in camelCase, keeping an `_` before a digit so the name converts back:
|
|
316
|
+
* `sales_2025` stays, `wb2_sales` is `wb2Sales`. The client decodes model-level names the same way.
|
|
317
|
+
*/
|
|
318
|
+
type CamelCase<S extends string> = S extends `${infer Head}_${infer Tail}` ? Tail extends `${Digit}${string}` ? `${Head}_${CamelCase<Tail>}` : `${Head}${Capitalize<CamelCase<Tail>>}` : S;
|
|
319
|
+
/** `entity.metric` for every metric of every entity, warehouse-backed or stored. */
|
|
320
|
+
type EntityMetricsOf<E> = E extends unknown ? `${CamelCase<NameOf<E>>}.${MetricsOf<E>}` : never;
|
|
321
|
+
/**
|
|
322
|
+
* The model metrics, `defineOntology({ metrics })`, by their bare declared names, or under their
|
|
323
|
+
* earlier name from an ontology SDK before manifest version 14. An ontology SDK without them, or a
|
|
324
|
+
* definition typed as any record of metrics, names none.
|
|
325
|
+
*/
|
|
326
|
+
type ModelMetricsOf<O> = (O extends {
|
|
327
|
+
readonly config: {
|
|
328
|
+
readonly metrics?: infer M;
|
|
329
|
+
};
|
|
330
|
+
} ? DeclaredNames<NonNullable<M>> : never) | EarlierModelMetricsOf<O>;
|
|
331
|
+
/** A route picks how an entity with metrics reaches a property, so only such entities start one. */
|
|
332
|
+
type RoutesOf<E, O> = [MetricsOf<E>] extends [never] ? never : PathsOf<E, O>;
|
|
333
|
+
/**
|
|
334
|
+
* `entity.property` for every entity's scalar properties, and `id` for stored entities, plus the
|
|
335
|
+
* routes `entity.relationship.property` from each entity with metrics.
|
|
336
|
+
*/
|
|
337
|
+
type ModelDimensionsOf<E, O> = E extends unknown ? `${CamelCase<NameOf<E>>}.${FieldsOf<E> | RoutesOf<E, O>}` : never;
|
|
338
|
+
/**
|
|
339
|
+
* `segmentstream.ontology.queryMetrics`: `POST /api/ontology/query_metrics`, as the signed-in user,
|
|
340
|
+
* who needs read permission on every entity the request reaches.
|
|
341
|
+
*/
|
|
342
|
+
export interface MetricQueryClient<Metric extends string = string, Dimension extends string = string> extends EarlierQueryMetricsName<Metric, Dimension> {
|
|
343
|
+
readonly queryMetrics: (request: MetricQuery<Metric, Dimension>, options?: RequestOptions) => Promise<MetricQueryResult>;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* `segmentstream.ontology.<entity>.queryMetrics`: `POST /api/ontology/<entity>/query_metrics`, the
|
|
347
|
+
* entity's own metrics by the names relative to it, as the signed-in user.
|
|
348
|
+
*/
|
|
349
|
+
export interface EntityMetricQueryClient<Property extends string = string, Metric extends string = string, Temporal extends Property = Property, Path extends string = never> extends EarlierEntityQueryMetricsName<Property, Metric, Temporal, Path> {
|
|
350
|
+
readonly queryMetrics: (request: EntityMetricQuery<Property, Metric, Temporal, Path>, options?: RequestOptions) => Promise<MetricQueryResult>;
|
|
351
|
+
}
|
|
352
|
+
type ClientOf<E, O> = IsWarehouseBacked<E> extends true ? Pick<EntityClient<RecordOf<E>, never>, "find" | "query" | "get"> & EntityMetricQueryClient<keyof PropertiesOf<E> & string, MetricsOf<E>, keyof PropertiesOf<E> & string, PathsOf<E, O>> : EntityClient<RecordOf<E>, ActionClients<ActionsOf<E>> & (NameOf<E> extends "user" ? UserGeneratedActions<RecordOf<E>> : unknown), GeneratedOf<E>>;
|
|
353
|
+
type TypedOntologyClient<O> = {
|
|
354
|
+
readonly [N in NameOf<EntitiesOf<O>>]: ClientOf<Extract<EntitiesOf<O>, {
|
|
355
|
+
readonly name: N;
|
|
356
|
+
}>, O>;
|
|
357
|
+
} & MetricQueryClient<EntityMetricsOf<EntitiesOf<O>> | ModelMetricsOf<O>, ModelDimensionsOf<EntitiesOf<O>, O>>;
|
|
358
|
+
/** A client for any entity, when the app passes no ontology type. */
|
|
359
|
+
export type UntypedOntologyClient = MetricQueryClient & {
|
|
360
|
+
readonly [entity: string]: EntityClient<JsonRecord, {
|
|
361
|
+
readonly [action: string]: ActionCall<JsonRecord, JsonValue>;
|
|
362
|
+
}> & EntityMetricQueryClient;
|
|
363
|
+
};
|
|
364
|
+
/**
|
|
365
|
+
* `segmentstream.ontology`: one client per entity of `O`, the type of the app's ontology
|
|
366
|
+
* (`typeof ontology`), and `queryMetrics` across them, a name no entity takes. Without `O`, any
|
|
367
|
+
* entity name is accepted and records are untyped.
|
|
368
|
+
*/
|
|
369
|
+
export type OntologyClient<O = unknown> = unknown extends O ? UntypedOntologyClient : TypedOntologyClient<O>;
|
|
370
|
+
/** Sends one ontology request with the caller's credentials. Paths are below `/api/ontology`. */
|
|
371
|
+
export interface OntologyTransport {
|
|
372
|
+
readonly fetch: (path: string, init: RequestInit) => Promise<Response>;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Entities and actions exist only in the app's types, so the client resolves them by name when
|
|
376
|
+
* they are used: `ontology.lead.actions.changeStatus(…)` posts to `lead/actions/change_status`.
|
|
377
|
+
*/
|
|
378
|
+
export declare function createOntologyClient<O>(transport: OntologyTransport): OntologyClient<O>;
|
|
379
|
+
/** `find` sends the query as URL parameters: `where` as JSON, `orderBy` as `field:direction`. */
|
|
380
|
+
export declare function findParameters(query: ReadQuery): URLSearchParams;
|
|
381
|
+
export {};
|