@forumulate/sdk 0.4.0 → 0.7.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/dist/index.d.ts CHANGED
@@ -1,16 +1,18 @@
1
1
  export * from './types';
2
- export { verifyWebhookSignature, type VerifyWebhookInput } from './webhooks';
3
- export type { paths } from './schema';
2
+ export { verifyWebhookSignature, constructWebhookEvent, type VerifyWebhookInput } from './webhooks';
3
+ export * from './content';
4
+ export * from './translations';
5
+ export type { paths, operations } from './schema';
4
6
  export type { HttpMethod, MethodsOf, OperationOf, TypedRequestInit, TypedResponse } from './typed';
7
+ export { ForumulateError, SDK_VERSION, retryDelayMs, type CallOptions, type ForumulateErrorInit, } from './http';
8
+ export { rowsOf, type PagePromise } from './pagination';
9
+ export type { Namespace, NamespaceName, OperationArgs, OperationFn, OperationId, OperationResult, OperationRow, PagedOperationId, Resources, } from './resources';
10
+ export { API_VERSION } from './operations.gen';
5
11
  import type { paths } from './schema';
6
12
  import type { HttpMethod, TypedRequestInit, TypedResponse } from './typed';
7
- import type { Organization, Space, SpaceType, SpaceVisibility, Collection, Page, BlockDoc, SearchHit, UnifiedHit, Comment, Webhook, WebhookFormat, PublicPage, Conformance, DomainSetup, DomainSummary, Item, PageInfo, EffectiveShape, ShapeOverride } from './types';
8
- /** Thrown for any non-2xx API response. Mirrors the API's error envelope. */
9
- export declare class ForumulateError extends Error {
10
- readonly status: number;
11
- readonly code: string;
12
- constructor(status: number, code: string, message: string);
13
- }
13
+ import { type Query } from './http';
14
+ import { type PositionalHelpers } from './helpers';
15
+ import { type Merged, type Namespace, type OperationArgs, type OptionalArgsOperationId, type OperationId, type OperationReturn, type OperationRow, type PagedOperationId, type Resources } from './resources';
14
16
  export interface ForumulateClientOptions {
15
17
  /** API base, `https://forumulate.com/api` for the hosted product (see `fromEnv`). */
16
18
  baseUrl: string;
@@ -32,25 +34,57 @@ export interface ForumulateClientOptions {
32
34
  * from the SDK that advertised it.
33
35
  */
34
36
  headers?: Record<string, string>;
37
+ /**
38
+ * The `Forumulate-Version` to state. The namespace methods and
39
+ * `request(operationId)` always state one — this, or {@link API_VERSION}
40
+ * (the version the SDK was generated against) — because auto-pagination reads
41
+ * the envelope only a versioned answer carries. The 0.5 positional helpers,
42
+ * `typed()` and `request(method, path)` send it only when you set it here,
43
+ * so code written against them sees exactly the answers it always saw.
44
+ */
45
+ apiVersion?: string;
46
+ /**
47
+ * Retries for 408/429/502/503/504 and network failures. Default 2. Only
48
+ * requests that are safe to repeat are retried: GET/PUT/DELETE, and writes
49
+ * carrying an `Idempotency-Key`. `Retry-After` is honoured.
50
+ */
51
+ maxRetries?: number;
52
+ /**
53
+ * Give every POST and PATCH a generated `Idempotency-Key` (the same one on
54
+ * each of its retries), so a write that timed out can be retried without
55
+ * running twice. Default true; a key you pass always wins.
56
+ */
57
+ autoIdempotencyKey?: boolean;
58
+ /**
59
+ * The `User-Agent` outside a browser. Default `forumulate-sdk-js/<version>`:
60
+ * the edge challenges default library agents, which reads as an outage to a
61
+ * first-time integration. Ignored where the runtime forbids the header.
62
+ */
63
+ userAgent?: string;
35
64
  }
36
- type Query = Record<string, string | number | boolean | undefined>;
65
+ type HandWritten = keyof PositionalHelpers | 'content';
37
66
  /**
38
67
  * Typed client for the Forumulate REST API.
39
68
  *
40
69
  * ```ts
41
70
  * const forumulate = new ForumulateClient({ baseUrl: 'https://forumulate.com/api', token: pat });
42
- * const { orgs } = await forumulate.orgs.list();
71
+ *
72
+ * for await (const post of forumulate.blog.list({ orgId, spaceId })) console.log(post);
73
+ * await forumulate.webhooks.rotate({ orgId, webhookId });
74
+ * await forumulate.request('Space_get', { orgId, spaceId });
43
75
  *
44
76
  * // or, from FORUMULATE_TOKEN / FORUMULATE_URL:
45
77
  * const fromEnv = ForumulateClient.fromEnv();
46
78
  * ```
79
+ *
80
+ * Every operation in the API is a method: `client.<namespace>[.<sub>].<method>`,
81
+ * named after its operationId (`ForumTopics_list` → `forum.topics.list`).
47
82
  */
83
+ export interface ForumulateClient extends Omit<Resources, HandWritten> {
84
+ }
48
85
  export declare class ForumulateClient {
49
- private readonly baseUrl;
50
- private readonly token?;
51
- private readonly credentials;
52
- private readonly defaultHeaders;
53
- private readonly _fetch;
86
+ private readonly transport;
87
+ private readonly apiVersion?;
54
88
  constructor(opts: ForumulateClientOptions);
55
89
  /**
56
90
  * A client configured from the environment, by the same names the CLI and
@@ -66,7 +100,18 @@ export declare class ForumulateClient {
66
100
  * anything in `opts` overrides what the environment said.
67
101
  */
68
102
  static fromEnv(env?: Record<string, string | undefined>, opts?: Partial<ForumulateClientOptions>): ForumulateClient;
69
- /** Low-level request. Exposed so callers can reach endpoints the typed helpers don't cover yet. */
103
+ /**
104
+ * Call any operation by its operationId, fully typed:
105
+ *
106
+ * ```ts
107
+ * const { space } = await forumulate.request('Space_get', { orgId, spaceId });
108
+ * ```
109
+ *
110
+ * The two-string form `request(method, path, opts)` is the untyped escape
111
+ * hatch it has always been.
112
+ */
113
+ request<K extends OptionalArgsOperationId>(operationId: K, args?: OperationArgs<NoInfer<K>>): OperationReturn<K>;
114
+ request<K extends OperationId>(operationId: K, args: OperationArgs<NoInfer<K>>): OperationReturn<K>;
70
115
  request<T>(method: string, path: string, opts?: {
71
116
  body?: unknown;
72
117
  query?: Query;
@@ -74,55 +119,37 @@ export declare class ForumulateClient {
74
119
  headers?: Record<string, string>;
75
120
  }): Promise<T>;
76
121
  /**
77
- * Fully-typed request against ANY endpoint in the OpenAPI spec.
122
+ * Every row of a paged operation, across every page — the same walk a
123
+ * namespace `list` gives, by operationId.
124
+ *
125
+ * ```ts
126
+ * for await (const space of forumulate.paginate('Space_list', { orgId })) { … }
127
+ * ```
128
+ */
129
+ paginate<K extends PagedOperationId & OptionalArgsOperationId>(operationId: K, args?: OperationArgs<NoInfer<K>>): AsyncIterable<OperationRow<K>>;
130
+ paginate<K extends PagedOperationId>(operationId: K, args: OperationArgs<NoInfer<K>>): AsyncIterable<OperationRow<K>>;
131
+ /**
132
+ * Fully-typed request against ANY endpoint in the OpenAPI spec, by path.
78
133
  *
79
- * Where the ~30 hand-written helpers above cover the stable, ergonomic
80
- * surface, `typed` covers the *whole* API: the generated `paths` interface
81
- * (`src/schema.ts`, produced from `openapi.json`) infers the path params,
82
- * query params, JSON body and success response for the `(method, path)` you
83
- * pass, so every one of the 600+ routes gets types and autocomplete without a
84
- * bespoke wrapper. Path templates like `/orgs/{orgId}/spaces` are filled from
85
- * `init.params`.
134
+ * The generated `paths` interface (`src/schema.ts`, produced from
135
+ * `openapi.json`) infers the path params, query params, JSON body and success
136
+ * response for the `(method, path)` you pass. Path templates like
137
+ * `/orgs/{orgId}/spaces` are filled from `init.params`.
86
138
  *
87
139
  * ```ts
88
- * // GET a list — path param is required and checked; response is typed.
89
140
  * const { spaces } = await forumulate.typed('get', '/orgs/{orgId}/spaces', {
90
- * params: { orgId }, query: { deleted: 'false', limit: '50', cursor: '' },
91
- * });
92
- *
93
- * // POST with a body the spec knows the shape of.
94
- * await forumulate.typed('post', '/orgs/{orgId}/spaces', {
95
- * params: { orgId },
96
- * body: { name: 'Docs', slug: 'docs', type: 'DOCS', visibility: 'PUBLIC' },
141
+ * params: { orgId }, query: { limit: 50 },
97
142
  * });
98
143
  * ```
99
- *
100
- * Regenerate the types after an API change with
101
- * `pnpm --filter @forumulate/sdk dump-spec` then
102
- * `npx openapi-typescript packages/sdk/openapi.json -o src/schema.ts`.
103
144
  */
104
145
  typed<P extends keyof paths, M extends keyof paths[P] & HttpMethod>(method: M, path: P, init: TypedRequestInit<paths[P][M]>): Promise<TypedResponse<paths[P][M]>>;
105
- private toError;
106
- readonly auth: {
107
- register: (input: {
108
- email: string;
109
- name: string;
110
- password: string;
111
- }) => Promise<{
112
- user: {
113
- id: string;
114
- email: string;
115
- };
116
- }>;
117
- login: (input: {
118
- email: string;
119
- password: string;
120
- }) => Promise<{
121
- user: {
122
- id: string;
123
- email: string;
124
- };
125
- }>;
146
+ /** The 0.5 door: no version stated unless the client pins one. */
147
+ private http;
148
+ /** The generated door: path filled from the args, version always stated, lists iterable. */
149
+ private readonly invoke;
150
+ private ns;
151
+ private readonly helpers;
152
+ readonly auth: Merged<Namespace<"auth">, {
126
153
  me: () => Promise<{
127
154
  user: {
128
155
  id: string;
@@ -130,7 +157,6 @@ export declare class ForumulateClient {
130
157
  name: string;
131
158
  };
132
159
  }>;
133
- /** Mint a Personal Access Token (requires an authenticated session). */
134
160
  createToken: (input: {
135
161
  name: string;
136
162
  scopes?: string[];
@@ -141,65 +167,376 @@ export declare class ForumulateClient {
141
167
  name: string;
142
168
  };
143
169
  }>;
170
+ }>;
171
+ readonly content: Merged<Namespace<"content">, {
172
+ libraries: {
173
+ list: (orgId: string) => Promise<{
174
+ libraries: import("./content").ContentLibrary[];
175
+ }>;
176
+ get: (orgId: string, libraryId: string) => Promise<{
177
+ library: import("./content").ContentLibrary;
178
+ }>;
179
+ create: (orgId: string, input: {
180
+ name: string;
181
+ slug?: string;
182
+ siteId?: string | null;
183
+ settings?: Record<string, unknown>;
184
+ template?: string;
185
+ }) => Promise<{
186
+ library: import("./content").ContentLibrary;
187
+ }>;
188
+ update: (orgId: string, libraryId: string, input: {
189
+ name?: string;
190
+ slug?: string;
191
+ siteId?: string | null;
192
+ settings?: Record<string, unknown>;
193
+ }) => Promise<{
194
+ library: import("./content").ContentLibrary;
195
+ }>;
196
+ remove: (orgId: string, libraryId: string) => Promise<{
197
+ ok: true;
198
+ }>;
199
+ };
200
+ members: {
201
+ list: (orgId: string, libraryId: string) => Promise<{
202
+ members: import("./content").LibraryMember[];
203
+ }>;
204
+ put: (orgId: string, libraryId: string, input: {
205
+ userId: string;
206
+ role?: import("./content").LibraryRole;
207
+ customRoleId?: string;
208
+ effect?: "ALLOW" | "DENY";
209
+ }) => Promise<{
210
+ member: import("./content").LibraryMember;
211
+ }>;
212
+ remove: (orgId: string, libraryId: string, userId: string) => Promise<{
213
+ ok: true;
214
+ }>;
215
+ };
216
+ model: {
217
+ get: (orgId: string, libraryId: string) => Promise<{
218
+ model: import("./content").ContentModel;
219
+ }>;
220
+ save: (orgId: string, libraryId: string, input: {
221
+ shape?: Record<string, unknown>;
222
+ types?: Record<string, unknown>;
223
+ ops?: import("./content").ModelOp[];
224
+ }) => Promise<{
225
+ model: import("./content").ContentModel;
226
+ }>;
227
+ versions: (orgId: string, libraryId: string) => Promise<{
228
+ versions: import("./content").ContentModelVersion[];
229
+ }>;
230
+ export: (orgId: string, libraryId: string, format?: import("./content").ModelFileFormat) => Promise<import("./content").ContentModelExport>;
231
+ import: (orgId: string, libraryId: string, input: {
232
+ format: import("./content").ModelFileFormat;
233
+ content: string;
234
+ dryRun?: boolean;
235
+ baseVersion?: number;
236
+ force?: boolean;
237
+ ops?: import("./content").ModelOp[];
238
+ }) => Promise<import("./content").ContentModelImportResult>;
239
+ schema: (orgId: string, libraryId: string, opts?: {
240
+ audience?: "public" | "preview";
241
+ }) => Promise<Record<string, unknown>>;
242
+ };
243
+ entries: {
244
+ create: (orgId: string, libraryId: string, input: {
245
+ title: string;
246
+ slug?: string;
247
+ preset: string;
248
+ params?: Record<string, unknown>;
249
+ }, idempotencyKey: string) => Promise<{
250
+ item: import("./content").ContentEntryRef;
251
+ warnings?: string[];
252
+ }>;
253
+ lookup: (orgId: string, libraryId: string, keys: string[]) => Promise<{
254
+ found: Record<string, string>;
255
+ }>;
256
+ update: (orgId: string, libraryId: string, entryId: string, input: {
257
+ title?: string;
258
+ slug?: string;
259
+ params?: Record<string, unknown>;
260
+ }) => Promise<{
261
+ item: import("./content").ContentEntryRef;
262
+ warnings?: string[];
263
+ }>;
264
+ writeLocale: (orgId: string, libraryId: string, entryId: string, locale: string, fields: Record<string, unknown>) => Promise<{
265
+ locale: string;
266
+ sourceEntryId: string;
267
+ entryId: string;
268
+ created: boolean;
269
+ }>;
270
+ read: (orgId: string, libraryId: string, entryId: string) => Promise<{
271
+ item: import("./content").ContentEntryRef & {
272
+ contentHash: string;
273
+ };
274
+ }>;
275
+ setFields: (orgId: string, libraryId: string, entryId: string, fields: Record<string, unknown>, ifMatch?: string) => Promise<{
276
+ fields: Record<string, unknown>;
277
+ warnings?: string[];
278
+ }>;
279
+ publish: (orgId: string, libraryId: string, entryId: string, ifMatch?: string) => Promise<{
280
+ published: boolean;
281
+ note?: string;
282
+ }>;
283
+ };
284
+ locales: {
285
+ list: (orgId: string, libraryId: string) => Promise<{
286
+ sourceLocale: string;
287
+ locales: {
288
+ code: string;
289
+ label: string;
290
+ }[];
291
+ }>;
292
+ add: (orgId: string, libraryId: string, input: {
293
+ code: string;
294
+ label: string;
295
+ }) => Promise<{
296
+ sourceLocale: string;
297
+ locales: {
298
+ code: string;
299
+ label: string;
300
+ }[];
301
+ }>;
302
+ };
303
+ assets: {
304
+ list: (orgId: string, libraryId: string, query?: {
305
+ search?: string;
306
+ limit?: number;
307
+ }) => Promise<{
308
+ assets: import("./content").ContentAssetSummary[];
309
+ }>;
310
+ };
311
+ keys: {
312
+ list: (orgId: string, libraryId: string) => Promise<{
313
+ keys: import("./content").DeliveryKeySummary[];
314
+ }>;
315
+ create: (orgId: string, libraryId: string, input: {
316
+ name: string;
317
+ kind: import("./content").DeliveryKeyKind;
318
+ origins?: string[];
319
+ contentTypes?: string[];
320
+ locales?: string[];
321
+ expiresInDays?: number;
322
+ }) => Promise<import("./content").IssuedDeliveryKey>;
323
+ update: (orgId: string, libraryId: string, keyId: string, input: {
324
+ name?: string;
325
+ origins?: string[] | null;
326
+ contentTypes?: string[] | null;
327
+ locales?: string[] | null;
328
+ }) => Promise<{
329
+ key: import("./content").DeliveryKeySummary;
330
+ }>;
331
+ rotate: (orgId: string, libraryId: string, keyId: string, input?: {
332
+ graceMinutes?: number;
333
+ }) => Promise<import("./content").IssuedDeliveryKey>;
334
+ revoke: (orgId: string, libraryId: string, keyId: string) => Promise<{
335
+ ok: true;
336
+ }>;
337
+ };
338
+ }>;
339
+ /** Translations of every kind of piece, routed by space type — see ./translations. */
340
+ readonly translations: {
341
+ locales: {
342
+ list: (orgId: string, target: import("./translations").LocaleTarget) => Promise<import("./translations").TranslationLocale[]>;
343
+ add: (orgId: string, target: import("./translations").LocaleTarget, input: {
344
+ code: string;
345
+ label: string;
346
+ }) => Promise<{
347
+ code: string;
348
+ label: string;
349
+ isSource: boolean;
350
+ }[]>;
351
+ relabel: (orgId: string, target: import("./translations").LocaleTarget, code: string, label: string) => Promise<{
352
+ code: string;
353
+ label: string;
354
+ isSource: boolean;
355
+ }[]>;
356
+ remove: (orgId: string, target: import("./translations").LocaleTarget, code: string) => Promise<{
357
+ code: string;
358
+ label: string;
359
+ isSource: boolean;
360
+ }[]>;
361
+ set: (orgId: string, target: import("./translations").LocaleTarget, want: {
362
+ code: string;
363
+ label: string;
364
+ }[], opts?: {
365
+ prune?: boolean;
366
+ }) => Promise<{
367
+ locales: import("./translations").TranslationLocale[];
368
+ added: string[];
369
+ relabeled: string[];
370
+ removed: string[];
371
+ }>;
372
+ };
373
+ status: (orgId: string, spaceId: string) => Promise<import("./translations").TranslationCoverage>;
374
+ list: (orgId: string, spaceId: string, pieceId: string, opts?: {
375
+ door?: import("./translations").TranslationDoor;
376
+ }) => Promise<{
377
+ translations: unknown[];
378
+ }>;
379
+ get: (orgId: string, spaceId: string, pieceId: string, locale: string, opts?: {
380
+ door?: import("./translations").TranslationDoor;
381
+ }) => Promise<import("./translations").PieceTranslation>;
382
+ put: (orgId: string, spaceId: string, pieceId: string, locale: string, input: import("./translations").PieceTranslationInput, opts?: {
383
+ door?: import("./translations").TranslationDoor;
384
+ }) => Promise<import("./translations").PieceTranslation>;
385
+ remove: (orgId: string, spaceId: string, pieceId: string, locale: string, opts?: {
386
+ door?: import("./translations").TranslationDoor;
387
+ }) => Promise<void>;
388
+ auto: (orgId: string, spaceId: string, pieceId: string, locale: string, opts?: import("./translations").AutoTranslateOptions & {
389
+ door?: import("./translations").TranslationDoor;
390
+ }) => Promise<{
391
+ translation: unknown;
392
+ }>;
393
+ autoEntry: (orgId: string, libraryId: string, entryId: string, locale: string, opts?: {
394
+ force?: boolean;
395
+ }) => Promise<{
396
+ locale: string;
397
+ results: {
398
+ entryId: string;
399
+ ok: boolean;
400
+ translationEntryId: string | null;
401
+ error: string | null;
402
+ }[];
403
+ }>;
404
+ setItemLocale: (orgId: string, spaceId: string, itemId: string, locale: string | null) => Promise<{
405
+ item: {
406
+ id: string;
407
+ locale?: string | null;
408
+ };
409
+ }>;
410
+ names: {
411
+ get: (orgId: string, spaceId: string, opts?: {
412
+ collectionId?: string;
413
+ }) => Promise<import("./translations").NamedTranslations>;
414
+ set: (orgId: string, spaceId: string, locale: string, words: {
415
+ name?: string;
416
+ description?: string;
417
+ } | null, opts?: {
418
+ collectionId?: string;
419
+ }) => Promise<import("./translations").NamedTranslations>;
420
+ };
421
+ entryLocale: {
422
+ get: (orgId: string, libraryId: string, entryId: string, locale: string) => Promise<{
423
+ entryId: string;
424
+ locale: string;
425
+ fields: Record<string, unknown>;
426
+ }>;
427
+ put: (orgId: string, libraryId: string, entryId: string, locale: string, fields: Record<string, unknown>) => Promise<{
428
+ locale: string;
429
+ sourceEntryId: string;
430
+ entryId: string;
431
+ created: boolean;
432
+ }>;
433
+ };
434
+ labels: {
435
+ strings: (orgId: string, scope: import("./translations").LabelScope) => Promise<{
436
+ languages: string[];
437
+ labels: import("./translations").LabelDictionary;
438
+ strings: unknown[];
439
+ coverage: Record<string, {
440
+ translated: number;
441
+ total: number;
442
+ }>;
443
+ }>;
444
+ replace: (orgId: string, scope: import("./translations").LabelScope, labels: import("./translations").LabelDictionary) => Promise<{
445
+ labels: import("./translations").LabelDictionary;
446
+ }>;
447
+ merge: (orgId: string, scope: import("./translations").LabelScope, labels: Record<string, Record<string, unknown> | null>) => Promise<{
448
+ labels: import("./translations").LabelDictionary;
449
+ }>;
450
+ };
451
+ overrides: {
452
+ list: (orgId: string, locale?: string) => Promise<{
453
+ overrides: import("./translations").TranslationOverride[];
454
+ }>;
455
+ set: (orgId: string, input: {
456
+ locale: string;
457
+ key: string;
458
+ value: string;
459
+ }) => Promise<{
460
+ override: import("./translations").TranslationOverride;
461
+ }>;
462
+ remove: (orgId: string, input: {
463
+ locale: string;
464
+ key: string;
465
+ }) => Promise<{
466
+ ok: true;
467
+ }>;
468
+ catalog: (orgId: string) => Promise<{
469
+ catalog: Record<string, string>;
470
+ }>;
471
+ forLocale: (orgId: string, locale: string) => Promise<{
472
+ overrides: Record<string, string>;
473
+ }>;
474
+ };
475
+ switcher: {
476
+ get: (orgId: string) => Promise<Record<string, unknown>>;
477
+ set: (orgId: string, config: Record<string, unknown>) => Promise<Record<string, unknown>>;
478
+ };
479
+ deepl: {
480
+ status: (orgId: string) => Promise<{
481
+ configured: boolean;
482
+ }>;
483
+ connect: (orgId: string, apiKey: string) => Promise<{
484
+ ok: true;
485
+ }>;
486
+ disconnect: (orgId: string) => Promise<{
487
+ ok: true;
488
+ }>;
489
+ };
144
490
  };
145
- readonly orgs: {
491
+ readonly orgs: Merged<Namespace<"orgs">, {
146
492
  list: () => Promise<{
147
- orgs: Organization[];
493
+ orgs: import("./types").Organization[];
148
494
  }>;
149
495
  create: (input: {
150
496
  name: string;
151
497
  slug: string;
152
498
  }) => Promise<{
153
- organization: Organization;
499
+ organization: import("./types").Organization;
154
500
  }>;
155
- };
156
- readonly spaces: {
501
+ }>;
502
+ readonly spaces: Merged<Namespace<"spaces">, {
157
503
  list: (orgId: string) => Promise<{
158
- spaces: Space[];
504
+ spaces: import("./types").Space[];
159
505
  }>;
160
506
  create: (orgId: string, input: {
161
507
  name: string;
162
508
  slug: string;
163
- type: SpaceType;
164
- visibility: SpaceVisibility;
509
+ type: import("./types").SpaceType;
510
+ visibility: import("./types").SpaceVisibility;
165
511
  }) => Promise<{
166
- space: Space;
512
+ space: import("./types").Space;
167
513
  }>;
168
514
  createCollection: (orgId: string, spaceId: string, input: {
169
515
  name: string;
170
516
  slug: string;
171
517
  }) => Promise<{
172
- collection: Collection;
518
+ collection: import("./types").Collection;
173
519
  }>;
174
520
  createPage: (orgId: string, spaceId: string, collectionId: string, input: {
175
521
  title: string;
176
522
  slug: string;
177
523
  }) => Promise<{
178
- page: Page;
524
+ page: import("./types").Page;
179
525
  }>;
180
526
  setPageContent: (orgId: string, spaceId: string, pageId: string, input: {
181
527
  title: string;
182
- content: BlockDoc;
528
+ content: import("./types").BlockDoc;
183
529
  }) => Promise<{
184
- page: Page;
530
+ page: import("./types").Page;
185
531
  }>;
186
532
  publishPage: (orgId: string, spaceId: string, pageId: string) => Promise<{
187
- page: Page;
533
+ page: import("./types").Page;
188
534
  }>;
189
- };
190
- /**
191
- * Shapes and pieces — the surface an agent works through.
192
- *
193
- * `shape` says what one piece of a space is made of and hands back JSON
194
- * Schema; `items` writes one, whatever a piece happens to be in that space:
195
- * a documentation page, a blog post, a release, an incident. The reply says
196
- * which required sections are still empty, so an agent can create a piece,
197
- * ask what it forgot, and close the gap.
198
- */
199
- readonly shapes: {
535
+ }>;
536
+ readonly shapes: Merged<Namespace<"shapes">, {
200
537
  get: (orgId: string, spaceId: string) => Promise<{
201
- shape: EffectiveShape;
202
- base: EffectiveShape;
538
+ shape: import("./types").EffectiveShape;
539
+ base: import("./types").EffectiveShape;
203
540
  presets: {
204
541
  name: string;
205
542
  label: string;
@@ -207,133 +544,91 @@ export declare class ForumulateClient {
207
544
  }[];
208
545
  jsonSchema: Record<string, unknown>;
209
546
  }>;
210
- set: (orgId: string, spaceId: string, patch: ShapeOverride) => Promise<{
211
- shape: EffectiveShape;
547
+ set: (orgId: string, spaceId: string, patch: import("./types").ShapeOverride) => Promise<{
548
+ shape: import("./types").EffectiveShape;
212
549
  }>;
213
550
  applyPreset: (orgId: string, spaceId: string, name: string) => Promise<{
214
- shape: EffectiveShape;
551
+ shape: import("./types").EffectiveShape;
215
552
  }>;
216
- };
217
- readonly items: {
553
+ }>;
554
+ readonly items: Merged<Namespace<"items">, {
218
555
  create: (orgId: string, spaceId: string, input: {
219
556
  title: string;
220
557
  slug?: string;
221
- /** Which kind of piece, where the space holds more than one. */
222
558
  preset?: string | null;
223
559
  sections?: Record<string, string>;
224
560
  body?: string;
225
561
  params?: Record<string, unknown>;
226
562
  }) => Promise<{
227
- item: Item;
228
- }>;
229
- /**
230
- * What is in a space: how something finds a piece it has no words for.
231
- *
232
- * Pass `include: ['body']` to get content. Asking for `sections` ALONE is
233
- * the trap: it is populated only for pieces written against a shape, so a
234
- * space of free-form pages answers with empty objects and a sync carries
235
- * nothing while reporting success. Every row says which field holds its
236
- * content in `contentIn`.
237
- *
238
- * Any option here puts the response in its paged form, so `page` and
239
- * `sync` come back — `page.total` is what a walk should check its own
240
- * count against, and `sync.checkpoint` is what an incremental sync stores.
241
- */
563
+ item: import("./types").Item;
564
+ }>;
242
565
  list: (orgId: string, spaceId: string, opts?: number | {
243
566
  limit?: number;
244
567
  include?: ("sections" | "body")[];
245
568
  cursor?: string;
246
- /** A `sync.checkpoint` from a previous walk, not a timestamp you made. */
247
569
  updatedSince?: string;
248
570
  includeDeleted?: boolean;
249
571
  fields?: string[];
250
572
  }) => Promise<{
251
- items: Item[];
252
- page?: PageInfo;
573
+ items: import("./types").Item[];
574
+ page?: import("./types").PageInfo;
253
575
  sync?: {
254
576
  checkpoint: string;
255
577
  };
256
578
  }>;
257
579
  get: (orgId: string, spaceId: string, itemId: string) => Promise<{
258
- item: Item & {
580
+ item: import("./types").Item & {
259
581
  sections: Record<string, string>;
260
582
  };
261
583
  }>;
262
- /**
263
- * Make it readable. Kinds that are live on creation say so and change nothing.
264
- *
265
- * `conformance` describes the piece AFTER publishing — which declared slots
266
- * are filled and which are still missing — so an agent that has just made
267
- * its work readable can tell a complete piece from one with holes in it
268
- * without fetching it again. The server has always sent it and this type
269
- * omitted it, so a TypeScript caller could not see the field the docs
270
- * promise (E-11).
271
- */
272
584
  publish: (orgId: string, spaceId: string, itemId: string) => Promise<{
273
585
  published: boolean;
274
586
  note?: string;
275
- conformance: Conformance;
276
- }>;
277
- /**
278
- * Replace a piece's whole body — as markdown, or as blocks.
279
- *
280
- * The create door has always taken markdown and this one took blocks only,
281
- * so "make it from this file" worked and "update it from the same file" did
282
- * not. Both now; blocks win if a caller sends both.
283
- */
587
+ conformance: import("./types").Conformance;
588
+ }>;
284
589
  setContent: (orgId: string, spaceId: string, itemId: string, input: {
285
590
  body?: string;
286
- content?: BlockDoc;
591
+ content?: import("./types").BlockDoc;
287
592
  }) => Promise<{
288
- conformance: Conformance;
593
+ conformance: import("./types").Conformance;
289
594
  }>;
290
- /** Replace one named section. Idempotent — sending it twice writes it once. */
291
595
  setSection: (orgId: string, spaceId: string, itemId: string, key: string, markdown: string) => Promise<{
292
- conformance: Conformance;
596
+ conformance: import("./types").Conformance;
293
597
  }>;
294
- };
295
- /**
296
- * The addresses a space answers at.
297
- *
298
- * Published because the question a customer asks about a custom domain —
299
- * "why is it not live yet" — is answerable only from `verified`, `active` and
300
- * the setup records, and the SDK could not reach any of them (DX-2). A failed
301
- * verification is a 200 with `verified: false`: read the body, not the status.
302
- */
303
- readonly domains: {
598
+ }>;
599
+ readonly domains: Merged<Namespace<"domains">, {
304
600
  list: (orgId: string, spaceId: string) => Promise<{
305
- domains: DomainSummary[];
601
+ domains: import("./types").DomainSummary[];
306
602
  }>;
307
603
  add: (orgId: string, spaceId: string, input: {
308
604
  hostname: string;
309
605
  basePath?: string;
310
606
  }) => Promise<{
311
- domain: DomainSummary;
607
+ domain: import("./types").DomainSummary;
312
608
  }>;
313
- /** Re-run the ownership check. `activate: false` proves it without switching traffic. */
314
609
  verify: (orgId: string, spaceId: string, domainId: string, activate?: boolean) => Promise<{
315
- domain: DomainSummary;
610
+ domain: import("./types").DomainSummary;
316
611
  }>;
317
- /** Switch traffic to an address whose ownership is already proven. */
318
612
  activate: (orgId: string, spaceId: string, domainId: string) => Promise<{
319
- domain: DomainSummary;
613
+ domain: import("./types").DomainSummary;
320
614
  }>;
321
- /** What to configure, and what is still missing. */
322
- setup: (orgId: string, spaceId: string, domainId: string) => Promise<DomainSetup>;
323
- };
324
- readonly webhooks: {
615
+ setup: (orgId: string, spaceId: string, domainId: string) => Promise<import("./types").DomainSetup>;
616
+ }>;
617
+ readonly webhooks: Merged<Namespace<"webhooks">, {
325
618
  list: (orgId: string) => Promise<{
326
- webhooks: Webhook[];
619
+ webhooks: import("./types").Webhook[];
327
620
  }>;
328
621
  create: (orgId: string, input: {
329
622
  url: string;
330
623
  events: string[];
331
- format?: WebhookFormat;
624
+ format?: import("./types").WebhookFormat;
332
625
  }) => Promise<{
333
- webhook: Webhook;
626
+ webhook: import("./types").Webhook;
334
627
  }>;
335
- };
336
- readonly snapshots: {
628
+ verifySignature: typeof import("./webhooks").verifyWebhookSignature;
629
+ constructEvent: typeof import("./webhooks").constructWebhookEvent;
630
+ }>;
631
+ readonly snapshots: Merged<Namespace<"snapshots">, {
337
632
  list: (orgId: string, spaceId: string) => Promise<{
338
633
  snapshots: unknown[];
339
634
  }>;
@@ -344,8 +639,8 @@ export declare class ForumulateClient {
344
639
  restored: number;
345
640
  skipped: number;
346
641
  }>;
347
- };
348
- readonly forum: {
642
+ }>;
643
+ readonly forum: Merged<Namespace<"forum">, {
349
644
  listTopics: (orgId: string, spaceId: string, query?: {
350
645
  sort?: string;
351
646
  category?: string;
@@ -356,48 +651,47 @@ export declare class ForumulateClient {
356
651
  }>;
357
652
  createTopic: (orgId: string, spaceId: string, input: {
358
653
  title: string;
359
- content: BlockDoc;
654
+ content: import("./types").BlockDoc;
360
655
  kind?: string;
361
656
  tags?: string[];
362
657
  categoryId?: string | null;
363
658
  }) => Promise<{
364
659
  topic: unknown;
365
660
  }>;
366
- reply: (orgId: string, spaceId: string, topicId: string, content: BlockDoc) => Promise<{
661
+ reply: (orgId: string, spaceId: string, topicId: string, content: import("./types").BlockDoc) => Promise<{
367
662
  post: unknown;
368
663
  }>;
369
- };
370
- readonly search: {
664
+ }>;
665
+ readonly search: Merged<Namespace<"search">, {
371
666
  unified: (orgId: string, q: string, opts?: {
372
667
  type?: string;
373
668
  limit?: number;
374
669
  }) => Promise<{
375
- hits: UnifiedHit[];
670
+ hits: import("./types").UnifiedHit[];
376
671
  }>;
377
- };
378
- readonly analytics: {
672
+ }>;
673
+ readonly analytics: Merged<Namespace<"analytics">, {
379
674
  orgEvents: (orgId: string, days?: number) => Promise<unknown>;
380
- };
381
- readonly public: {
382
- getPage: (orgId: string, spaceId: string, pageId: string) => Promise<PublicPage>;
675
+ }>;
676
+ readonly public: Merged<Namespace<"public">, {
677
+ getPage: (orgId: string, spaceId: string, pageId: string) => Promise<import("./types").PublicPage>;
383
678
  search: (orgId: string, spaceId: string, query: string) => Promise<{
384
- hits: SearchHit[];
679
+ hits: import("./types").SearchHit[];
385
680
  }>;
386
681
  listComments: (orgId: string, spaceId: string, pageId: string) => Promise<{
387
- comments: Comment[];
682
+ comments: import("./types").Comment[];
388
683
  }>;
389
684
  postComment: (orgId: string, spaceId: string, pageId: string, input: {
390
685
  authorName: string;
391
686
  body: string;
392
687
  parentId?: string | null;
393
688
  }) => Promise<{
394
- comment: Comment;
689
+ comment: import("./types").Comment;
395
690
  }>;
396
691
  reactToComment: (orgId: string, spaceId: string, commentId: string, emoji: string) => Promise<{
397
- comment: Comment;
692
+ comment: import("./types").Comment;
398
693
  }>;
399
- /** Download the whole space as a PDF. Returns the raw `Response` (read `.blob()` / `.arrayBuffer()`). */
400
694
  pdf: (orgId: string, spaceId: string) => Promise<Response>;
401
- };
695
+ }>;
402
696
  }
403
697
  //# sourceMappingURL=index.d.ts.map