@forumulate/sdk 0.4.0 → 0.5.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.
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Content libraries (headless CMS): the management routes under
3
+ * `/orgs/{orgId}/content/libraries/{libraryId}/…`.
4
+ *
5
+ * Hand-written because the generated `schema.ts` is refreshed from the
6
+ * DEPLOYED spec, and these routes are newer than the last refresh; `typed()`
7
+ * covers them once it catches up. Everything is addressed by `libraryId`,
8
+ * never by the hidden space behind a library: that id is not part of the
9
+ * contract (spec 14).
10
+ */
11
+ type Request = <T>(method: string, path: string, opts?: {
12
+ body?: unknown;
13
+ query?: Record<string, string | number | boolean | undefined>;
14
+ headers?: Record<string, string>;
15
+ }) => Promise<T>;
16
+ export interface ContentLibrary {
17
+ id: string;
18
+ name: string;
19
+ slug: string;
20
+ siteId: string | null;
21
+ settings: Record<string, unknown>;
22
+ createdAt: string;
23
+ updatedAt: string;
24
+ }
25
+ export type LibraryRole = 'viewer' | 'editor' | 'manager';
26
+ export interface LibraryMember {
27
+ userId: string;
28
+ email: string;
29
+ name: string;
30
+ role: LibraryRole | null;
31
+ customRoleId: string | null;
32
+ effect: 'ALLOW' | 'DENY';
33
+ }
34
+ /** A declared model change a diff cannot infer (a rename), or a removal. */
35
+ export type ModelOp = {
36
+ op: 'renameField';
37
+ type?: string;
38
+ blockType?: string;
39
+ from: string;
40
+ to: string;
41
+ } | {
42
+ op: 'removeField';
43
+ type?: string;
44
+ blockType?: string;
45
+ path: string;
46
+ } | {
47
+ op: 'restoreField';
48
+ type?: string;
49
+ blockType?: string;
50
+ path: string;
51
+ } | {
52
+ op: 'renameType';
53
+ from: string;
54
+ to: string;
55
+ } | {
56
+ op: 'renameBlockType';
57
+ from: string;
58
+ to: string;
59
+ };
60
+ export interface ContentModel {
61
+ shape: Record<string, unknown>;
62
+ types: Record<string, unknown>;
63
+ version: number;
64
+ }
65
+ export interface ContentModelVersion {
66
+ version: number;
67
+ ops: ModelOp[];
68
+ createdBy: string | null;
69
+ createdAt: string;
70
+ migratedAt: string | null;
71
+ }
72
+ export type ModelFileFormat = 'json' | 'payload';
73
+ export interface ModelFileIssue {
74
+ path: string;
75
+ kind: 'hook' | 'access' | 'component' | 'function' | 'lossy' | 'unsupported' | 'ignored' | 'rewritten';
76
+ message: string;
77
+ }
78
+ export interface ContentModelExport {
79
+ format: ModelFileFormat;
80
+ filename: string;
81
+ content: string;
82
+ version: number;
83
+ issues: ModelFileIssue[];
84
+ }
85
+ export interface ModelChangeLine {
86
+ op: 'add' | 'remove' | 'change';
87
+ target: 'type' | 'setting' | 'field' | 'blockType' | 'blockField';
88
+ type?: string;
89
+ blockType?: string;
90
+ path?: string;
91
+ property?: string;
92
+ before?: unknown;
93
+ after?: unknown;
94
+ }
95
+ export interface ContentModelImportResult {
96
+ changed: boolean;
97
+ applied: boolean;
98
+ diff: ModelChangeLine[];
99
+ storageOnly: boolean;
100
+ ops: ModelOp[];
101
+ issues: ModelFileIssue[];
102
+ version: number;
103
+ }
104
+ /** An entry as the management API answers a write: enough to address it again. */
105
+ export interface ContentEntryRef {
106
+ id: string;
107
+ title: string;
108
+ slug?: string;
109
+ preset?: string | null;
110
+ }
111
+ export interface ContentAssetSummary {
112
+ id: string;
113
+ url: string;
114
+ filename: string;
115
+ contentType?: string;
116
+ [extra: string]: unknown;
117
+ }
118
+ export type DeliveryKeyKind = 'delivery' | 'publishable' | 'preview';
119
+ export interface DeliveryKeySummary {
120
+ id: string;
121
+ name: string;
122
+ kind: DeliveryKeyKind;
123
+ prefix: string;
124
+ stage: 'published' | 'draft';
125
+ libraryId: string;
126
+ origins: string[] | null;
127
+ contentTypes: string[] | null;
128
+ locales: string[] | null;
129
+ lastUsedAt: string | null;
130
+ [extra: string]: unknown;
131
+ }
132
+ export interface IssuedDeliveryKey {
133
+ key: DeliveryKeySummary;
134
+ /** Shown once. */
135
+ secret: string;
136
+ }
137
+ export declare function contentApi(request: Request): {
138
+ libraries: {
139
+ list: (orgId: string) => Promise<{
140
+ libraries: ContentLibrary[];
141
+ }>;
142
+ get: (orgId: string, libraryId: string) => Promise<{
143
+ library: ContentLibrary;
144
+ }>;
145
+ create: (orgId: string, input: {
146
+ name: string;
147
+ slug?: string;
148
+ siteId?: string | null;
149
+ settings?: Record<string, unknown>;
150
+ template?: string;
151
+ }) => Promise<{
152
+ library: ContentLibrary;
153
+ }>;
154
+ update: (orgId: string, libraryId: string, input: {
155
+ name?: string;
156
+ slug?: string;
157
+ siteId?: string | null;
158
+ settings?: Record<string, unknown>;
159
+ }) => Promise<{
160
+ library: ContentLibrary;
161
+ }>;
162
+ remove: (orgId: string, libraryId: string) => Promise<{
163
+ ok: true;
164
+ }>;
165
+ };
166
+ members: {
167
+ list: (orgId: string, libraryId: string) => Promise<{
168
+ members: LibraryMember[];
169
+ }>;
170
+ put: (orgId: string, libraryId: string, input: {
171
+ userId: string;
172
+ role?: LibraryRole;
173
+ customRoleId?: string;
174
+ effect?: "ALLOW" | "DENY";
175
+ }) => Promise<{
176
+ member: LibraryMember;
177
+ }>;
178
+ remove: (orgId: string, libraryId: string, userId: string) => Promise<{
179
+ ok: true;
180
+ }>;
181
+ };
182
+ model: {
183
+ get: (orgId: string, libraryId: string) => Promise<{
184
+ model: ContentModel;
185
+ }>;
186
+ save: (orgId: string, libraryId: string, input: {
187
+ shape?: Record<string, unknown>;
188
+ types?: Record<string, unknown>;
189
+ ops?: ModelOp[];
190
+ }) => Promise<{
191
+ model: ContentModel;
192
+ }>;
193
+ versions: (orgId: string, libraryId: string) => Promise<{
194
+ versions: ContentModelVersion[];
195
+ }>;
196
+ /** The model as a file: `forumulate.content.json`, or a Payload config. */
197
+ export: (orgId: string, libraryId: string, format?: ModelFileFormat) => Promise<ContentModelExport>;
198
+ /** Push a model file: a diff always, a new version unless `dryRun` (or nothing changed). */
199
+ import: (orgId: string, libraryId: string, input: {
200
+ format: ModelFileFormat;
201
+ content: string;
202
+ dryRun?: boolean;
203
+ baseVersion?: number;
204
+ force?: boolean;
205
+ ops?: ModelOp[];
206
+ }) => Promise<ContentModelImportResult>;
207
+ /** The library's delivery JSON Schema (what `forumulate content types` generates from). */
208
+ schema: (orgId: string, libraryId: string, opts?: {
209
+ audience?: "public" | "preview";
210
+ }) => Promise<Record<string, unknown>>;
211
+ };
212
+ /**
213
+ * Entries by their management id. `create` takes an `Idempotency-Key` (the
214
+ * route requires one), so a retried import returns the entry the first call
215
+ * made. Later writes may carry the entry's `contentHash` as `If-Match`; an import is the only writer, so it sends none.
216
+ */
217
+ entries: {
218
+ create: (orgId: string, libraryId: string, input: {
219
+ title: string;
220
+ slug?: string;
221
+ preset: string;
222
+ params?: Record<string, unknown>;
223
+ }, idempotencyKey: string) => Promise<{
224
+ item: ContentEntryRef;
225
+ warnings?: string[];
226
+ }>;
227
+ /** Which of these `Idempotency-Key`s already made an entry, as key → entry id (an import's dry-run and its update path). */
228
+ lookup: (orgId: string, libraryId: string, keys: string[]) => Promise<{
229
+ found: Record<string, string>;
230
+ }>;
231
+ /** Rename, re-address or patch the fields (`params`) of an entry. */
232
+ update: (orgId: string, libraryId: string, entryId: string, input: {
233
+ title?: string;
234
+ slug?: string;
235
+ params?: Record<string, unknown>;
236
+ }) => Promise<{
237
+ item: ContentEntryRef;
238
+ warnings?: string[];
239
+ }>;
240
+ /** Write an entry's localized fields into the DRAFT of one locale's twin, making the twin first when needed. */
241
+ writeLocale: (orgId: string, libraryId: string, entryId: string, locale: string, fields: Record<string, unknown>) => Promise<{
242
+ locale: string;
243
+ sourceEntryId: string;
244
+ entryId: string;
245
+ created: boolean;
246
+ }>;
247
+ read: (orgId: string, libraryId: string, entryId: string) => Promise<{
248
+ item: ContentEntryRef & {
249
+ contentHash: string;
250
+ };
251
+ }>;
252
+ setFields: (orgId: string, libraryId: string, entryId: string, fields: Record<string, unknown>, ifMatch?: string) => Promise<{
253
+ fields: Record<string, unknown>;
254
+ warnings?: string[];
255
+ }>;
256
+ publish: (orgId: string, libraryId: string, entryId: string, ifMatch?: string) => Promise<{
257
+ published: boolean;
258
+ note?: string;
259
+ }>;
260
+ };
261
+ locales: {
262
+ list: (orgId: string, libraryId: string) => Promise<{
263
+ sourceLocale: string;
264
+ locales: {
265
+ code: string;
266
+ label: string;
267
+ }[];
268
+ }>;
269
+ add: (orgId: string, libraryId: string, input: {
270
+ code: string;
271
+ label: string;
272
+ }) => Promise<{
273
+ sourceLocale: string;
274
+ locales: {
275
+ code: string;
276
+ label: string;
277
+ }[];
278
+ }>;
279
+ };
280
+ assets: {
281
+ list: (orgId: string, libraryId: string, query?: {
282
+ search?: string;
283
+ limit?: number;
284
+ }) => Promise<{
285
+ assets: ContentAssetSummary[];
286
+ }>;
287
+ };
288
+ keys: {
289
+ list: (orgId: string, libraryId: string) => Promise<{
290
+ keys: DeliveryKeySummary[];
291
+ }>;
292
+ create: (orgId: string, libraryId: string, input: {
293
+ name: string;
294
+ kind: DeliveryKeyKind;
295
+ origins?: string[];
296
+ contentTypes?: string[];
297
+ locales?: string[];
298
+ expiresInDays?: number;
299
+ }) => Promise<IssuedDeliveryKey>;
300
+ update: (orgId: string, libraryId: string, keyId: string, input: {
301
+ name?: string;
302
+ origins?: string[] | null;
303
+ contentTypes?: string[] | null;
304
+ locales?: string[] | null;
305
+ }) => Promise<{
306
+ key: DeliveryKeySummary;
307
+ }>;
308
+ rotate: (orgId: string, libraryId: string, keyId: string, input?: {
309
+ graceMinutes?: number;
310
+ }) => Promise<IssuedDeliveryKey>;
311
+ revoke: (orgId: string, libraryId: string, keyId: string) => Promise<{
312
+ ok: true;
313
+ }>;
314
+ };
315
+ };
316
+ export type ContentApi = ReturnType<typeof contentApi>;
317
+ export {};
318
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * Content libraries (headless CMS): the management routes under
4
+ * `/orgs/{orgId}/content/libraries/{libraryId}/…`.
5
+ *
6
+ * Hand-written because the generated `schema.ts` is refreshed from the
7
+ * DEPLOYED spec, and these routes are newer than the last refresh; `typed()`
8
+ * covers them once it catches up. Everything is addressed by `libraryId`,
9
+ * never by the hidden space behind a library: that id is not part of the
10
+ * contract (spec 14).
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.contentApi = contentApi;
14
+ function contentApi(request) {
15
+ const lib = (orgId, libraryId) => `/orgs/${orgId}/content/libraries/${libraryId}`;
16
+ return {
17
+ libraries: {
18
+ list: (orgId) => request('GET', `/orgs/${orgId}/content/libraries`),
19
+ get: (orgId, libraryId) => request('GET', lib(orgId, libraryId)),
20
+ create: (orgId, input) => request('POST', `/orgs/${orgId}/content/libraries`, { body: input }),
21
+ update: (orgId, libraryId, input) => request('PATCH', lib(orgId, libraryId), { body: input }),
22
+ remove: (orgId, libraryId) => request('DELETE', lib(orgId, libraryId)),
23
+ },
24
+ members: {
25
+ list: (orgId, libraryId) => request('GET', `${lib(orgId, libraryId)}/members`),
26
+ put: (orgId, libraryId, input) => request('POST', `${lib(orgId, libraryId)}/members`, { body: input }),
27
+ remove: (orgId, libraryId, userId) => request('DELETE', `${lib(orgId, libraryId)}/members/${userId}`),
28
+ },
29
+ model: {
30
+ get: (orgId, libraryId) => request('GET', `${lib(orgId, libraryId)}/model`),
31
+ save: (orgId, libraryId, input) => request('PUT', `${lib(orgId, libraryId)}/model`, { body: input }),
32
+ versions: (orgId, libraryId) => request('GET', `${lib(orgId, libraryId)}/model/versions`),
33
+ /** The model as a file: `forumulate.content.json`, or a Payload config. */
34
+ export: (orgId, libraryId, format = 'json') => request('GET', `${lib(orgId, libraryId)}/model/export`, { query: { format } }),
35
+ /** Push a model file: a diff always, a new version unless `dryRun` (or nothing changed). */
36
+ import: (orgId, libraryId, input) => request('POST', `${lib(orgId, libraryId)}/model/import`, { body: input }),
37
+ /** The library's delivery JSON Schema (what `forumulate content types` generates from). */
38
+ schema: (orgId, libraryId, opts = {}) => request('GET', `${lib(orgId, libraryId)}/model/schema.json`, { query: { audience: opts.audience } }),
39
+ },
40
+ /**
41
+ * Entries by their management id. `create` takes an `Idempotency-Key` (the
42
+ * route requires one), so a retried import returns the entry the first call
43
+ * made. Later writes may carry the entry's `contentHash` as `If-Match`; an import is the only writer, so it sends none.
44
+ */
45
+ entries: {
46
+ create: (orgId, libraryId, input, idempotencyKey) => request('POST', `${lib(orgId, libraryId)}/items`, {
47
+ body: input,
48
+ headers: { 'Idempotency-Key': idempotencyKey },
49
+ }),
50
+ /** Which of these `Idempotency-Key`s already made an entry, as key → entry id (an import's dry-run and its update path). */
51
+ lookup: (orgId, libraryId, keys) => request('POST', `${lib(orgId, libraryId)}/items/lookup`, { body: { keys } }),
52
+ /** Rename, re-address or patch the fields (`params`) of an entry. */
53
+ update: (orgId, libraryId, entryId, input) => request('PATCH', `${lib(orgId, libraryId)}/items/${entryId}`, { body: input }),
54
+ /** Write an entry's localized fields into the DRAFT of one locale's twin, making the twin first when needed. */
55
+ writeLocale: (orgId, libraryId, entryId, locale, fields) => request('PUT', `${lib(orgId, libraryId)}/entries/${entryId}/locales/${encodeURIComponent(locale)}`, { body: { fields } }),
56
+ read: (orgId, libraryId, entryId) => request('GET', `${lib(orgId, libraryId)}/items/${entryId}`),
57
+ setFields: (orgId, libraryId, entryId, fields, ifMatch) => request('PATCH', `${lib(orgId, libraryId)}/items/${entryId}/fields`, {
58
+ body: { fields },
59
+ headers: ifMatch ? { 'If-Match': `"${ifMatch}"` } : undefined,
60
+ }),
61
+ publish: (orgId, libraryId, entryId, ifMatch) => request('POST', `${lib(orgId, libraryId)}/items/${entryId}/publish`, {
62
+ headers: ifMatch ? { 'If-Match': `"${ifMatch}"` } : undefined,
63
+ }),
64
+ },
65
+ locales: {
66
+ list: (orgId, libraryId) => request('GET', `${lib(orgId, libraryId)}/locales`),
67
+ add: (orgId, libraryId, input) => request('POST', `${lib(orgId, libraryId)}/locales`, { body: input }),
68
+ },
69
+ assets: {
70
+ list: (orgId, libraryId, query = {}) => request('GET', `${lib(orgId, libraryId)}/assets`, { query }),
71
+ },
72
+ keys: {
73
+ list: (orgId, libraryId) => request('GET', `${lib(orgId, libraryId)}/keys`),
74
+ create: (orgId, libraryId, input) => request('POST', `${lib(orgId, libraryId)}/keys`, { body: input }),
75
+ update: (orgId, libraryId, keyId, input) => request('PATCH', `${lib(orgId, libraryId)}/keys/${keyId}`, { body: input }),
76
+ rotate: (orgId, libraryId, keyId, input = {}) => request('POST', `${lib(orgId, libraryId)}/keys/${keyId}/rotate`, { body: input }),
77
+ revoke: (orgId, libraryId, keyId) => request('DELETE', `${lib(orgId, libraryId)}/keys/${keyId}`),
78
+ },
79
+ };
80
+ }
81
+ //# sourceMappingURL=content.js.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './types';
2
2
  export { verifyWebhookSignature, type VerifyWebhookInput } from './webhooks';
3
+ export * from './content';
3
4
  export type { paths } from './schema';
4
5
  export type { HttpMethod, MethodsOf, OperationOf, TypedRequestInit, TypedResponse } from './typed';
5
6
  import type { paths } from './schema';
@@ -142,6 +143,174 @@ export declare class ForumulateClient {
142
143
  };
143
144
  }>;
144
145
  };
146
+ readonly content: {
147
+ libraries: {
148
+ list: (orgId: string) => Promise<{
149
+ libraries: import("./content").ContentLibrary[];
150
+ }>;
151
+ get: (orgId: string, libraryId: string) => Promise<{
152
+ library: import("./content").ContentLibrary;
153
+ }>;
154
+ create: (orgId: string, input: {
155
+ name: string;
156
+ slug?: string;
157
+ siteId?: string | null;
158
+ settings?: Record<string, unknown>;
159
+ template?: string;
160
+ }) => Promise<{
161
+ library: import("./content").ContentLibrary;
162
+ }>;
163
+ update: (orgId: string, libraryId: string, input: {
164
+ name?: string;
165
+ slug?: string;
166
+ siteId?: string | null;
167
+ settings?: Record<string, unknown>;
168
+ }) => Promise<{
169
+ library: import("./content").ContentLibrary;
170
+ }>;
171
+ remove: (orgId: string, libraryId: string) => Promise<{
172
+ ok: true;
173
+ }>;
174
+ };
175
+ members: {
176
+ list: (orgId: string, libraryId: string) => Promise<{
177
+ members: import("./content").LibraryMember[];
178
+ }>;
179
+ put: (orgId: string, libraryId: string, input: {
180
+ userId: string;
181
+ role?: import("./content").LibraryRole;
182
+ customRoleId?: string;
183
+ effect?: "ALLOW" | "DENY";
184
+ }) => Promise<{
185
+ member: import("./content").LibraryMember;
186
+ }>;
187
+ remove: (orgId: string, libraryId: string, userId: string) => Promise<{
188
+ ok: true;
189
+ }>;
190
+ };
191
+ model: {
192
+ get: (orgId: string, libraryId: string) => Promise<{
193
+ model: import("./content").ContentModel;
194
+ }>;
195
+ save: (orgId: string, libraryId: string, input: {
196
+ shape?: Record<string, unknown>;
197
+ types?: Record<string, unknown>;
198
+ ops?: import("./content").ModelOp[];
199
+ }) => Promise<{
200
+ model: import("./content").ContentModel;
201
+ }>;
202
+ versions: (orgId: string, libraryId: string) => Promise<{
203
+ versions: import("./content").ContentModelVersion[];
204
+ }>;
205
+ export: (orgId: string, libraryId: string, format?: import("./content").ModelFileFormat) => Promise<import("./content").ContentModelExport>;
206
+ import: (orgId: string, libraryId: string, input: {
207
+ format: import("./content").ModelFileFormat;
208
+ content: string;
209
+ dryRun?: boolean;
210
+ baseVersion?: number;
211
+ force?: boolean;
212
+ ops?: import("./content").ModelOp[];
213
+ }) => Promise<import("./content").ContentModelImportResult>;
214
+ schema: (orgId: string, libraryId: string, opts?: {
215
+ audience?: "public" | "preview";
216
+ }) => Promise<Record<string, unknown>>;
217
+ };
218
+ entries: {
219
+ create: (orgId: string, libraryId: string, input: {
220
+ title: string;
221
+ slug?: string;
222
+ preset: string;
223
+ params?: Record<string, unknown>;
224
+ }, idempotencyKey: string) => Promise<{
225
+ item: import("./content").ContentEntryRef;
226
+ warnings?: string[];
227
+ }>;
228
+ lookup: (orgId: string, libraryId: string, keys: string[]) => Promise<{
229
+ found: Record<string, string>;
230
+ }>;
231
+ update: (orgId: string, libraryId: string, entryId: string, input: {
232
+ title?: string;
233
+ slug?: string;
234
+ params?: Record<string, unknown>;
235
+ }) => Promise<{
236
+ item: import("./content").ContentEntryRef;
237
+ warnings?: string[];
238
+ }>;
239
+ writeLocale: (orgId: string, libraryId: string, entryId: string, locale: string, fields: Record<string, unknown>) => Promise<{
240
+ locale: string;
241
+ sourceEntryId: string;
242
+ entryId: string;
243
+ created: boolean;
244
+ }>;
245
+ read: (orgId: string, libraryId: string, entryId: string) => Promise<{
246
+ item: import("./content").ContentEntryRef & {
247
+ contentHash: string;
248
+ };
249
+ }>;
250
+ setFields: (orgId: string, libraryId: string, entryId: string, fields: Record<string, unknown>, ifMatch?: string) => Promise<{
251
+ fields: Record<string, unknown>;
252
+ warnings?: string[];
253
+ }>;
254
+ publish: (orgId: string, libraryId: string, entryId: string, ifMatch?: string) => Promise<{
255
+ published: boolean;
256
+ note?: string;
257
+ }>;
258
+ };
259
+ locales: {
260
+ list: (orgId: string, libraryId: string) => Promise<{
261
+ sourceLocale: string;
262
+ locales: {
263
+ code: string;
264
+ label: string;
265
+ }[];
266
+ }>;
267
+ add: (orgId: string, libraryId: string, input: {
268
+ code: string;
269
+ label: string;
270
+ }) => Promise<{
271
+ sourceLocale: string;
272
+ locales: {
273
+ code: string;
274
+ label: string;
275
+ }[];
276
+ }>;
277
+ };
278
+ assets: {
279
+ list: (orgId: string, libraryId: string, query?: {
280
+ search?: string;
281
+ limit?: number;
282
+ }) => Promise<{
283
+ assets: import("./content").ContentAssetSummary[];
284
+ }>;
285
+ };
286
+ keys: {
287
+ list: (orgId: string, libraryId: string) => Promise<{
288
+ keys: import("./content").DeliveryKeySummary[];
289
+ }>;
290
+ create: (orgId: string, libraryId: string, input: {
291
+ name: string;
292
+ kind: import("./content").DeliveryKeyKind;
293
+ origins?: string[];
294
+ contentTypes?: string[];
295
+ locales?: string[];
296
+ expiresInDays?: number;
297
+ }) => Promise<import("./content").IssuedDeliveryKey>;
298
+ update: (orgId: string, libraryId: string, keyId: string, input: {
299
+ name?: string;
300
+ origins?: string[] | null;
301
+ contentTypes?: string[] | null;
302
+ locales?: string[] | null;
303
+ }) => Promise<{
304
+ key: import("./content").DeliveryKeySummary;
305
+ }>;
306
+ rotate: (orgId: string, libraryId: string, keyId: string, input?: {
307
+ graceMinutes?: number;
308
+ }) => Promise<import("./content").IssuedDeliveryKey>;
309
+ revoke: (orgId: string, libraryId: string, keyId: string) => Promise<{
310
+ ok: true;
311
+ }>;
312
+ };
313
+ };
145
314
  readonly orgs: {
146
315
  list: () => Promise<{
147
316
  orgs: Organization[];
package/dist/index.js CHANGED
@@ -18,6 +18,8 @@ exports.ForumulateClient = exports.ForumulateError = exports.verifyWebhookSignat
18
18
  __exportStar(require("./types"), exports);
19
19
  var webhooks_1 = require("./webhooks");
20
20
  Object.defineProperty(exports, "verifyWebhookSignature", { enumerable: true, get: function () { return webhooks_1.verifyWebhookSignature; } });
21
+ __exportStar(require("./content"), exports);
22
+ const content_1 = require("./content");
21
23
  /** Thrown for any non-2xx API response. Mirrors the API's error envelope. */
22
24
  class ForumulateError extends Error {
23
25
  status;
@@ -194,6 +196,8 @@ class ForumulateClient {
194
196
  body: input,
195
197
  }),
196
198
  };
199
+ // ── Content libraries (headless CMS) — see ./content ───────────────────────
200
+ content = (0, content_1.contentApi)((method, path, opts) => this.request(method, path, opts));
197
201
  // ── Organizations ─────────────────────────────────────────────────────────
198
202
  orgs = {
199
203
  list: () => this.request('GET', '/orgs'),
package/dist/schema.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/schema.d.ts
3
- size: 35557853 bytes
4
- sha256: c980b7a7869774480b1b44e97a481782fc1fdbf58a91ddad38ba18cc43e39f87
3
+ size: 41197295 bytes
4
+ sha256: 4b7229f500f88ffae386167d2d8d14491e8afd8734cc89cde35ce316308ade7d
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumulate/sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Typed TypeScript client for the Forumulate REST API.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://forumulate.com/reference",