@forumulate/sdk 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Forumulate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # @forumulate/sdk
2
+
3
+ A typed TypeScript client for the Forumulate REST API. Works in Node 18+ (global
4
+ `fetch`) and the browser.
5
+
6
+ ## Install
7
+
8
+ Inside the monorepo it's a workspace package (`@forumulate/sdk`). For an external
9
+ app, publish it or copy `src/` — it has zero runtime dependencies.
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { ForumulateClient } from '@forumulate/sdk';
15
+
16
+ const forumulate = new ForumulateClient({
17
+ baseUrl: 'https://api.forumulate.example',
18
+ token: process.env.FORUMULATE_TOKEN, // a Personal Access Token
19
+ });
20
+
21
+ // Create an org + a public docs space with one published page.
22
+ const { organization } = await forumulate.orgs.create({ name: 'Acme', slug: 'acme' });
23
+ const { space } = await forumulate.spaces.create(organization.id, {
24
+ name: 'Docs', slug: 'docs', type: 'DOCS', visibility: 'PUBLIC',
25
+ });
26
+ const { collection } = await forumulate.spaces.createCollection(organization.id, space.id, {
27
+ name: 'Guides', slug: 'guides',
28
+ });
29
+ const { page } = await forumulate.spaces.createPage(organization.id, space.id, collection.id, {
30
+ title: 'Intro', slug: 'intro',
31
+ });
32
+ await forumulate.spaces.setPageContent(organization.id, space.id, page.id, {
33
+ title: 'Intro',
34
+ content: { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Hello!' }] }] },
35
+ });
36
+ await forumulate.spaces.publishPage(organization.id, space.id, page.id);
37
+
38
+ // Read it back through the public reader (no auth).
39
+ const { hits } = await forumulate.public.search(organization.id, space.id, 'hello');
40
+ ```
41
+
42
+ ### Errors
43
+
44
+ Every non-2xx response throws a `ForumulateError` carrying `status`, `code`, and
45
+ `message` from the API's error envelope.
46
+
47
+ ```ts
48
+ import { ForumulateError } from '@forumulate/sdk';
49
+ try {
50
+ await forumulate.orgs.create({ name: '', slug: '' });
51
+ } catch (err) {
52
+ if (err instanceof ForumulateError && err.code === 'validation.failed') { /* … */ }
53
+ }
54
+ ```
55
+
56
+ ### Session-cookie auth (browser)
57
+
58
+ ```ts
59
+ const forumulate = new ForumulateClient({ baseUrl: '/api', credentials: true });
60
+ ```
61
+
62
+ ### Typed coverage of every endpoint — `typed()`
63
+
64
+ The ~30 helpers above are the ergonomic surface. For the **whole** API (every
65
+ route in the OpenAPI spec — 600+ of them), use `typed(method, path, init)`. It
66
+ reads the machine-generated `paths` interface in `src/schema.ts` and infers the
67
+ path params, query params, JSON body and success response for whatever route you
68
+ name — with autocomplete on both the path and the method:
69
+
70
+ ```ts
71
+ // Path param required and checked; response payload is typed from the spec.
72
+ const { spaces } = await forumulate.typed('get', '/orgs/{orgId}/spaces', {
73
+ params: { orgId },
74
+ query: { deleted: 'false', limit: '50', cursor: '' },
75
+ });
76
+
77
+ // POST body shape (including enum unions like `type`) comes from the schema.
78
+ await forumulate.typed('post', '/orgs/{orgId}/spaces', {
79
+ params: { orgId },
80
+ body: { name: 'Docs', slug: 'docs', type: 'DOCS', visibility: 'PUBLIC' },
81
+ });
82
+ ```
83
+
84
+ `{param}` placeholders in the path are filled from `init.params`. Pass
85
+ `raw: true` to get the untouched `Response` (e.g. for binary downloads).
86
+
87
+ ### Escape hatch
88
+
89
+ Any endpoint is also reachable untyped via `request` (what `typed` and the
90
+ helpers delegate to):
91
+
92
+ ```ts
93
+ await forumulate.request('POST', `/orgs/${orgId}/spaces/${spaceId}/pages/${pageId}/publish`, { body: {} });
94
+ ```
95
+
96
+ ## Regenerating from the OpenAPI spec
97
+
98
+ `src/schema.ts` is the source of the typed-`typed()` coverage. It is generated,
99
+ types-only (no runtime dependency), and large (~30k lines) — do not hand-edit it.
100
+ The **complete** machine-readable spec is served by the running API at
101
+ `/docs-json`; regenerate `schema.ts` from it whenever the API shape changes:
102
+
103
+ ```bash
104
+ # 1. Dump the spec (boots the app in-memory; no server needed)
105
+ pnpm --filter @forumulate/sdk dump-spec # → packages/sdk/openapi.json
106
+
107
+ # 2a. Regenerate the path types that back typed()
108
+ pnpm --filter @forumulate/sdk generate-schema # → src/schema.ts
109
+ # (equivalently: npx openapi-typescript openapi.json -o src/schema.ts)
110
+
111
+ # 2b. …or generate a client in another language
112
+ npx @openapitools/openapi-generator-cli generate \
113
+ -i packages/sdk/openapi.json -g python -o ../forumulate-python
114
+ ```
@@ -0,0 +1,320 @@
1
+ export * from './types';
2
+ export { verifyWebhookSignature, type VerifyWebhookInput } from './webhooks';
3
+ export type { paths } from './schema';
4
+ export type { HttpMethod, MethodsOf, OperationOf, TypedRequestInit, TypedResponse, } from './typed';
5
+ import type { paths } from './schema';
6
+ import type { HttpMethod, TypedRequestInit, TypedResponse } from './typed';
7
+ import type { Organization, Space, SpaceType, SpaceVisibility, Collection, Page, BlockDoc, SearchHit, UnifiedHit, Comment, Webhook, WebhookFormat, PublicPage, Conformance, 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
+ }
14
+ export interface ForumulateClientOptions {
15
+ /** API origin, e.g. `https://api.forumulate.example` or `http://localhost:4000`. */
16
+ baseUrl: string;
17
+ /** Personal Access Token for `Authorization: Bearer` auth. */
18
+ token?: string;
19
+ /** Send the session cookie (browser same-origin usage). Default false. */
20
+ credentials?: boolean;
21
+ /** Injectable fetch (for tests / non-global-fetch runtimes). Defaults to global fetch. */
22
+ fetch?: typeof fetch;
23
+ }
24
+ type Query = Record<string, string | number | boolean | undefined>;
25
+ /**
26
+ * Typed client for the Forumulate REST API.
27
+ *
28
+ * ```ts
29
+ * const forumulate = new ForumulateClient({ baseUrl: 'http://localhost:4000', token: pat });
30
+ * const { organizations } = await forumulate.orgs.list();
31
+ * ```
32
+ */
33
+ export declare class ForumulateClient {
34
+ private readonly baseUrl;
35
+ private readonly token?;
36
+ private readonly credentials;
37
+ private readonly _fetch;
38
+ constructor(opts: ForumulateClientOptions);
39
+ /** Low-level request. Exposed so callers can reach endpoints the typed helpers don't cover yet. */
40
+ request<T>(method: string, path: string, opts?: {
41
+ body?: unknown;
42
+ query?: Query;
43
+ raw?: boolean;
44
+ }): Promise<T>;
45
+ /**
46
+ * Fully-typed request against ANY endpoint in the OpenAPI spec.
47
+ *
48
+ * Where the ~30 hand-written helpers above cover the stable, ergonomic
49
+ * surface, `typed` covers the *whole* API: the generated `paths` interface
50
+ * (`src/schema.ts`, produced from `openapi.json`) infers the path params,
51
+ * query params, JSON body and success response for the `(method, path)` you
52
+ * pass, so every one of the 600+ routes gets types and autocomplete without a
53
+ * bespoke wrapper. Path templates like `/orgs/{orgId}/spaces` are filled from
54
+ * `init.params`.
55
+ *
56
+ * ```ts
57
+ * // GET a list — path param is required and checked; response is typed.
58
+ * const { spaces } = await forumulate.typed('get', '/orgs/{orgId}/spaces', {
59
+ * params: { orgId }, query: { deleted: 'false', limit: '50', cursor: '' },
60
+ * });
61
+ *
62
+ * // POST with a body the spec knows the shape of.
63
+ * await forumulate.typed('post', '/orgs/{orgId}/spaces', {
64
+ * params: { orgId },
65
+ * body: { name: 'Docs', slug: 'docs', type: 'DOCS', visibility: 'PUBLIC' },
66
+ * });
67
+ * ```
68
+ *
69
+ * Regenerate the types after an API change with
70
+ * `pnpm --filter @forumulate/sdk dump-spec` then
71
+ * `npx openapi-typescript packages/sdk/openapi.json -o src/schema.ts`.
72
+ */
73
+ 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]>>;
74
+ private toError;
75
+ readonly auth: {
76
+ register: (input: {
77
+ email: string;
78
+ name: string;
79
+ password: string;
80
+ }) => Promise<{
81
+ user: {
82
+ id: string;
83
+ email: string;
84
+ };
85
+ }>;
86
+ login: (input: {
87
+ email: string;
88
+ password: string;
89
+ }) => Promise<{
90
+ user: {
91
+ id: string;
92
+ email: string;
93
+ };
94
+ }>;
95
+ me: () => Promise<{
96
+ user: {
97
+ id: string;
98
+ email: string;
99
+ name: string;
100
+ };
101
+ }>;
102
+ /** Mint a Personal Access Token (requires an authenticated session). */
103
+ createToken: (input: {
104
+ name: string;
105
+ scopes?: string[];
106
+ }) => Promise<{
107
+ token: string;
108
+ pat: {
109
+ id: string;
110
+ name: string;
111
+ };
112
+ }>;
113
+ };
114
+ readonly orgs: {
115
+ list: () => Promise<{
116
+ orgs: Organization[];
117
+ }>;
118
+ create: (input: {
119
+ name: string;
120
+ slug: string;
121
+ }) => Promise<{
122
+ organization: Organization;
123
+ }>;
124
+ };
125
+ readonly spaces: {
126
+ list: (orgId: string) => Promise<{
127
+ spaces: Space[];
128
+ }>;
129
+ create: (orgId: string, input: {
130
+ name: string;
131
+ slug: string;
132
+ type: SpaceType;
133
+ visibility: SpaceVisibility;
134
+ }) => Promise<{
135
+ space: Space;
136
+ }>;
137
+ createCollection: (orgId: string, spaceId: string, input: {
138
+ name: string;
139
+ slug: string;
140
+ }) => Promise<{
141
+ collection: Collection;
142
+ }>;
143
+ createPage: (orgId: string, spaceId: string, collectionId: string, input: {
144
+ title: string;
145
+ slug: string;
146
+ }) => Promise<{
147
+ page: Page;
148
+ }>;
149
+ setPageContent: (orgId: string, spaceId: string, pageId: string, input: {
150
+ title: string;
151
+ content: BlockDoc;
152
+ }) => Promise<{
153
+ page: Page;
154
+ }>;
155
+ publishPage: (orgId: string, spaceId: string, pageId: string) => Promise<{
156
+ page: Page;
157
+ }>;
158
+ };
159
+ /**
160
+ * Shapes and pieces — the surface an agent works through.
161
+ *
162
+ * `shape` says what one piece of a space is made of and hands back JSON
163
+ * Schema; `items` writes one, whatever a piece happens to be in that space:
164
+ * a documentation page, a blog post, a release, an incident. The reply says
165
+ * which required sections are still empty, so an agent can create a piece,
166
+ * ask what it forgot, and close the gap.
167
+ */
168
+ readonly shapes: {
169
+ get: (orgId: string, spaceId: string) => Promise<{
170
+ shape: EffectiveShape;
171
+ base: EffectiveShape;
172
+ presets: {
173
+ name: string;
174
+ label: string;
175
+ description: string;
176
+ }[];
177
+ jsonSchema: Record<string, unknown>;
178
+ }>;
179
+ set: (orgId: string, spaceId: string, patch: ShapeOverride) => Promise<{
180
+ shape: EffectiveShape;
181
+ }>;
182
+ applyPreset: (orgId: string, spaceId: string, name: string) => Promise<{
183
+ shape: EffectiveShape;
184
+ }>;
185
+ };
186
+ readonly items: {
187
+ create: (orgId: string, spaceId: string, input: {
188
+ title: string;
189
+ slug?: string;
190
+ /** Which kind of piece, where the space holds more than one. */
191
+ preset?: string | null;
192
+ sections?: Record<string, string>;
193
+ body?: string;
194
+ params?: Record<string, unknown>;
195
+ }) => Promise<{
196
+ item: Item;
197
+ }>;
198
+ /**
199
+ * What is in a space: how something finds a piece it has no words for.
200
+ *
201
+ * Pass `include: ['body']` to get content. Asking for `sections` ALONE is
202
+ * the trap: it is populated only for pieces written against a shape, so a
203
+ * space of free-form pages answers with empty objects and a sync carries
204
+ * nothing while reporting success. Every row says which field holds its
205
+ * content in `contentIn`.
206
+ *
207
+ * Any option here puts the response in its paged form, so `page` and
208
+ * `sync` come back — `page.total` is what a walk should check its own
209
+ * count against, and `sync.checkpoint` is what an incremental sync stores.
210
+ */
211
+ list: (orgId: string, spaceId: string, opts?: number | {
212
+ limit?: number;
213
+ include?: ("sections" | "body")[];
214
+ cursor?: string;
215
+ /** A `sync.checkpoint` from a previous walk, not a timestamp you made. */
216
+ updatedSince?: string;
217
+ includeDeleted?: boolean;
218
+ fields?: string[];
219
+ }) => Promise<{
220
+ items: Item[];
221
+ page?: PageInfo;
222
+ sync?: {
223
+ checkpoint: string;
224
+ };
225
+ }>;
226
+ get: (orgId: string, spaceId: string, itemId: string) => Promise<{
227
+ item: Item & {
228
+ sections: Record<string, string>;
229
+ };
230
+ }>;
231
+ /** Make it readable. Kinds that are live on creation say so and change nothing. */
232
+ publish: (orgId: string, spaceId: string, itemId: string) => Promise<{
233
+ published: boolean;
234
+ note?: string;
235
+ }>;
236
+ /** Replace one named section. Idempotent — sending it twice writes it once. */
237
+ setSection: (orgId: string, spaceId: string, itemId: string, key: string, markdown: string) => Promise<{
238
+ conformance: Conformance;
239
+ }>;
240
+ };
241
+ readonly webhooks: {
242
+ list: (orgId: string) => Promise<{
243
+ webhooks: Webhook[];
244
+ }>;
245
+ create: (orgId: string, input: {
246
+ url: string;
247
+ events: string[];
248
+ format?: WebhookFormat;
249
+ }) => Promise<{
250
+ webhook: Webhook;
251
+ }>;
252
+ };
253
+ readonly snapshots: {
254
+ list: (orgId: string, spaceId: string) => Promise<{
255
+ snapshots: unknown[];
256
+ }>;
257
+ create: (orgId: string, spaceId: string, label: string) => Promise<{
258
+ snapshot: unknown;
259
+ }>;
260
+ restore: (orgId: string, spaceId: string, id: string) => Promise<{
261
+ restored: number;
262
+ skipped: number;
263
+ }>;
264
+ };
265
+ readonly forum: {
266
+ listTopics: (orgId: string, spaceId: string, query?: {
267
+ sort?: string;
268
+ category?: string;
269
+ page?: number;
270
+ }) => Promise<{
271
+ topics: unknown[];
272
+ hasMore?: boolean;
273
+ }>;
274
+ createTopic: (orgId: string, spaceId: string, input: {
275
+ title: string;
276
+ content: BlockDoc;
277
+ kind?: string;
278
+ tags?: string[];
279
+ categoryId?: string | null;
280
+ }) => Promise<{
281
+ topic: unknown;
282
+ }>;
283
+ reply: (orgId: string, spaceId: string, topicId: string, content: BlockDoc) => Promise<{
284
+ post: unknown;
285
+ }>;
286
+ };
287
+ readonly search: {
288
+ unified: (orgId: string, q: string, opts?: {
289
+ type?: string;
290
+ limit?: number;
291
+ }) => Promise<{
292
+ hits: UnifiedHit[];
293
+ }>;
294
+ };
295
+ readonly analytics: {
296
+ orgEvents: (orgId: string, days?: number) => Promise<unknown>;
297
+ };
298
+ readonly public: {
299
+ getPage: (orgId: string, spaceId: string, pageId: string) => Promise<PublicPage>;
300
+ search: (orgId: string, spaceId: string, query: string) => Promise<{
301
+ hits: SearchHit[];
302
+ }>;
303
+ listComments: (orgId: string, spaceId: string, pageId: string) => Promise<{
304
+ comments: Comment[];
305
+ }>;
306
+ postComment: (orgId: string, spaceId: string, pageId: string, input: {
307
+ authorName: string;
308
+ body: string;
309
+ parentId?: string | null;
310
+ }) => Promise<{
311
+ comment: Comment;
312
+ }>;
313
+ reactToComment: (orgId: string, spaceId: string, commentId: string, emoji: string) => Promise<{
314
+ comment: Comment;
315
+ }>;
316
+ /** Download the whole space as a PDF. Returns the raw `Response` (read `.blob()` / `.arrayBuffer()`). */
317
+ pdf: (orgId: string, spaceId: string) => Promise<Response>;
318
+ };
319
+ }
320
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}