@nohead/sdk 0.2.0 → 0.3.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,8 +1,8 @@
1
1
  export { Nohead } from "./client.ts";
2
2
  export { APIPromise, Page, PagePromise, type APIResponse, } from "./api-promise.ts";
3
- export type { ClientOptions, ConditionalRequestOptions, RequestOptions, RetryEvent, } from "./core.ts";
3
+ export type { ClientOptions, ConditionalRequestOptions, ConditionalWriteOptions, RequestOptions, RetryEvent, WriteOptions, } from "./core.ts";
4
4
  export { APIError, AbortError, AuthenticationError, AuthorizationError, ConflictError, ConnectionError, InternalServerError, InvalidRequestError, NoheadError, NotFoundError, PlanLimitExceededError, PreconditionFailedError, RateLimitError, ServiceUnavailableError, TimeoutError, UploadError, ValidationError, WebhookVerificationError, } from "./errors.ts";
5
5
  export type { Uploadable, UploadParams } from "./resources/assets.ts";
6
6
  export type * from "./types.ts";
7
- export { unwrapWebhook, type AssetEvent, type RecordEvent, type SchemaChangedEvent, type UnwrapOptions, type WebhookEvent, type WebhookHeaders, type WebhookTestEvent, } from "./webhooks.ts";
7
+ export { unwrapWebhook, type AssetEvent, type DraftEvent, type RecordEvent, type SchemaEvent, type FieldAliasRemovedEvent, type UnwrapOptions, type WebhookEvent, type WebhookHeaders, type WebhookTestEvent, } from "./webhooks.ts";
8
8
  export { VERSION } from "./version.ts";
@@ -1,6 +1,6 @@
1
1
  import type { APIPromise, PagePromise } from "../api-promise.ts";
2
2
  import type { RequestOptions } from "../core.ts";
3
- import type { Asset, AssetUpload, AssetUploadCreate, DownloadUrl, ImageUrl } from "../generated/types.gen.ts";
3
+ import type { Asset, AssetUploadCreate, AssetWithUpload, AssetUsage, DownloadUrl, ImageUrl } from "../generated/types.gen.ts";
4
4
  import type { AssetListParams, ImageUrlParams } from "../types.ts";
5
5
  import { Resource } from "./resource.ts";
6
6
  /** What `assets.upload` accepts. A stream needs `byte_size`. */
@@ -23,24 +23,43 @@ export declare class Assets extends Resource {
23
23
  *
24
24
  * With an `idempotencyKey`, running the same upload again resumes it: the
25
25
  * key starts the upload, and an asset that is already `ready` is returned
26
- * without sending the bytes again.
26
+ * without sending the bytes again. Once the upload's URL has expired
27
+ * (`upload.expires_at`), it throws `UploadError`: start over with a new key.
27
28
  *
28
29
  * import { openAsBlob } from "node:fs"
29
30
  * const asset = await nohead.assets.upload(await openAsBlob("a.jpg"), { filename: "a.jpg" })
30
31
  */
31
32
  upload(file: Uploadable, params?: UploadParams, options?: RequestOptions): Promise<Asset>;
32
33
  /**
33
- * The first step of an upload: a `pending` asset and a presigned URL to
34
- * `PUT` the bytes to (for example from a browser). Then `complete` it.
34
+ * The first step of an upload: a `pending` asset with its `upload`, a
35
+ * presigned URL to `PUT` the bytes to (for example from a browser). Then
36
+ * `complete` it.
35
37
  */
36
- createUpload(params: AssetUploadCreate, options?: RequestOptions): APIPromise<AssetUpload>;
38
+ createUpload(params: AssetUploadCreate, options?: RequestOptions): APIPromise<AssetWithUpload>;
37
39
  /** Checks an uploaded file and marks the asset `ready`. */
38
40
  complete(asset: string, options?: RequestOptions): APIPromise<Asset>;
39
41
  list(params?: AssetListParams, options?: RequestOptions): PagePromise<Asset>;
40
42
  get(asset: string, options?: RequestOptions): APIPromise<Asset>;
41
- /** Soft-deletes the asset; the file is purged after 30 days. */
43
+ /**
44
+ * Soft-deletes the asset: `restore` brings it back until its
45
+ * `purge_after`, when the file is purged (or now, with `purge`).
46
+ */
42
47
  delete(asset: string, options?: RequestOptions): APIPromise<Asset>;
43
48
  restore(asset: string, options?: RequestOptions): APIPromise<Asset>;
49
+ /**
50
+ * Permanently deletes a deleted asset now, instead of at its
51
+ * `purge_after`, and frees its storage. It can't be restored, records that use
52
+ * it keep an ID that no longer resolves, and its image URLs stop working
53
+ * within a minute or so. Returns the asset as it was. An asset that isn't
54
+ * deleted is a `ConflictError`: delete it first.
55
+ */
56
+ purge(asset: string, options?: RequestOptions): APIPromise<Asset>;
57
+ /**
58
+ * Where the asset is used: how many undeleted records use it (`records`),
59
+ * how many of those are published (`published`), and the 10 most recently
60
+ * updated with the fields that use it (`uses`). Needs `records:read` too.
61
+ */
62
+ usage(asset: string, options?: RequestOptions): APIPromise<AssetUsage>;
44
63
  /** A signed, cacheable URL of an image rendition (`url`). */
45
64
  imageUrl(asset: string, params?: ImageUrlParams, options?: RequestOptions): APIPromise<ImageUrl>;
46
65
  /** A 15-minute link to download the original file (`url`). */
@@ -1,5 +1,5 @@
1
1
  import { AbortError, UploadError } from "../errors.js";
2
- import { Resource } from "./resource.js";
2
+ import { listQuery, Resource } from "./resource.js";
3
3
  /** Files of the key's project. `asset` is an asset ID (`ast_…`). */
4
4
  export class Assets extends Resource {
5
5
  /**
@@ -10,7 +10,8 @@ export class Assets extends Resource {
10
10
  *
11
11
  * With an `idempotencyKey`, running the same upload again resumes it: the
12
12
  * key starts the upload, and an asset that is already `ready` is returned
13
- * without sending the bytes again.
13
+ * without sending the bytes again. Once the upload's URL has expired
14
+ * (`upload.expires_at`), it throws `UploadError`: start over with a new key.
14
15
  *
15
16
  * import { openAsBlob } from "node:fs"
16
17
  * const asset = await nohead.assets.upload(await openAsBlob("a.jpg"), { filename: "a.jpg" })
@@ -20,7 +21,7 @@ export class Assets extends Resource {
20
21
  if (byteSize === undefined) {
21
22
  throw new UploadError("Uploading a stream needs `byte_size`");
22
23
  }
23
- const { asset, upload } = await this.createUpload({
24
+ const { upload, ...asset } = await this.createUpload({
24
25
  filename: params.filename ??
25
26
  (typeof File !== "undefined" && file instanceof File
26
27
  ? file.name
@@ -34,10 +35,13 @@ export class Assets extends Resource {
34
35
  const current = await this.get(asset.id, {
35
36
  ...options,
36
37
  idempotencyKey: undefined,
37
- changeNote: undefined,
38
38
  });
39
39
  if (current.status === "ready")
40
40
  return current;
41
+ // The key replays the first run's upload URL, which expires sooner.
42
+ if (Date.parse(upload.expires_at) <= Date.now()) {
43
+ throw new UploadError(`The upload of ${asset.filename} expired: start it again with a new idempotencyKey`);
44
+ }
41
45
  }
42
46
  const stream = file instanceof ReadableStream;
43
47
  const response = await this.core
@@ -59,8 +63,9 @@ export class Assets extends Resource {
59
63
  return this.complete(asset.id, { ...options, idempotencyKey: undefined });
60
64
  }
61
65
  /**
62
- * The first step of an upload: a `pending` asset and a presigned URL to
63
- * `PUT` the bytes to (for example from a browser). Then `complete` it.
66
+ * The first step of an upload: a `pending` asset with its `upload`, a
67
+ * presigned URL to `PUT` the bytes to (for example from a browser). Then
68
+ * `complete` it.
64
69
  */
65
70
  createUpload(params, options) {
66
71
  return this.core.request("assets_upload", { body: params }, options);
@@ -70,18 +75,39 @@ export class Assets extends Resource {
70
75
  return this.core.request("assets_complete", { path: { asset_id: asset } }, options);
71
76
  }
72
77
  list(params = {}, options) {
73
- return this.core.paginate("assets_list", { query: params }, options);
78
+ return this.core.paginate("assets_list", { query: listQuery(params, ["deleted", "content_type"]) }, options);
74
79
  }
75
80
  get(asset, options) {
76
81
  return this.core.request("assets_get", { path: { asset_id: asset } }, options);
77
82
  }
78
- /** Soft-deletes the asset; the file is purged after 30 days. */
83
+ /**
84
+ * Soft-deletes the asset: `restore` brings it back until its
85
+ * `purge_after`, when the file is purged (or now, with `purge`).
86
+ */
79
87
  delete(asset, options) {
80
88
  return this.core.request("assets_delete", { path: { asset_id: asset } }, options);
81
89
  }
82
90
  restore(asset, options) {
83
91
  return this.core.request("assets_restore", { path: { asset_id: asset } }, options);
84
92
  }
93
+ /**
94
+ * Permanently deletes a deleted asset now, instead of at its
95
+ * `purge_after`, and frees its storage. It can't be restored, records that use
96
+ * it keep an ID that no longer resolves, and its image URLs stop working
97
+ * within a minute or so. Returns the asset as it was. An asset that isn't
98
+ * deleted is a `ConflictError`: delete it first.
99
+ */
100
+ purge(asset, options) {
101
+ return this.core.request("assets_purge", { path: { asset_id: asset } }, options);
102
+ }
103
+ /**
104
+ * Where the asset is used: how many undeleted records use it (`records`),
105
+ * how many of those are published (`published`), and the 10 most recently
106
+ * updated with the fields that use it (`uses`). Needs `records:read` too.
107
+ */
108
+ usage(asset, options) {
109
+ return this.core.request("assets_usage", { path: { asset_id: asset } }, options);
110
+ }
85
111
  /** A signed, cacheable URL of an image rendition (`url`). */
86
112
  imageUrl(asset, params = {}, options) {
87
113
  return this.core.request("assets_image_url", { path: { asset_id: asset }, query: params }, options);
@@ -0,0 +1,41 @@
1
+ import type { APIPromise, PagePromise } from "../api-promise.ts";
2
+ import type { ConditionalRequestOptions, ConditionalWriteOptions, RequestOptions } from "../core.ts";
3
+ import type { RecordData } from "../generated/types.gen.ts";
4
+ import type { DraftCreateParams, DraftGetParams, DraftListParams, DraftScheduleParams, DraftUpdateParams, NoheadDraft, NoheadRecord } from "../types.ts";
5
+ import { Resource } from "./resource.ts";
6
+ /**
7
+ * Drafts: changes to a record's content that wait until they are merged into
8
+ * it, now or at a set time, while the record keeps its current content. A
9
+ * record has at most one. `draft` is a draft ID (`drf_…`); `record` a record
10
+ * ID; `collection` a collection ID or slug. Like records, drafts take the
11
+ * type of their data: `drafts.get<Post>(id)`.
12
+ */
13
+ export declare class Drafts extends Resource {
14
+ /**
15
+ * Starts the record's draft, from the record's values (`data` over them),
16
+ * or from an earlier revision's (`from_revision`). A second is a
17
+ * `ConflictError` (detail code `draft_exists`, with its `draft_id`): update
18
+ * that one instead.
19
+ */
20
+ create<D = RecordData>(record: string, params?: DraftCreateParams<D>, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
21
+ /**
22
+ * A collection's drafts, most recently changed first. `record_id` narrows
23
+ * them to one record, or to several (1 to 100; an empty list is a
24
+ * `TypeError`, since it would match no record).
25
+ */
26
+ list<D = RecordData>(collection: string, { record_id, ...params }?: DraftListParams, options?: RequestOptions): PagePromise<NoheadDraft<D>>;
27
+ /** With `data` as the record reads after the merge, for previews. */
28
+ get<D = RecordData>(draft: string, params?: DraftGetParams, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
29
+ /** Sets the given fields (`null` clears one), as a record update does. */
30
+ update<D = RecordData>(draft: string, params: DraftUpdateParams<D>, options?: ConditionalRequestOptions): APIPromise<NoheadDraft<D>>;
31
+ /** Deletes the draft for good; returns it as it was. */
32
+ discard<D = RecordData>(draft: string, options?: ConditionalRequestOptions): APIPromise<NoheadDraft<D>>;
33
+ /**
34
+ * Applies the draft to its record now, as one `merge` revision, and
35
+ * returns the record. Content only: the record stays live or not.
36
+ */
37
+ merge<D = RecordData>(draft: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
38
+ /** Merges the draft at `merge_at`, a future time; returns the draft. */
39
+ schedule<D = RecordData>(draft: string, params: DraftScheduleParams, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
40
+ unschedule<D = RecordData>(draft: string, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
41
+ }
@@ -0,0 +1,63 @@
1
+ import { Resource } from "./resource.js";
2
+ /**
3
+ * Drafts: changes to a record's content that wait until they are merged into
4
+ * it, now or at a set time, while the record keeps its current content. A
5
+ * record has at most one. `draft` is a draft ID (`drf_…`); `record` a record
6
+ * ID; `collection` a collection ID or slug. Like records, drafts take the
7
+ * type of their data: `drafts.get<Post>(id)`.
8
+ */
9
+ export class Drafts extends Resource {
10
+ /**
11
+ * Starts the record's draft, from the record's values (`data` over them),
12
+ * or from an earlier revision's (`from_revision`). A second is a
13
+ * `ConflictError` (detail code `draft_exists`, with its `draft_id`): update
14
+ * that one instead.
15
+ */
16
+ create(record, params = {}, options) {
17
+ return this.core.request("drafts_create", { path: { record_id: record }, body: params }, options);
18
+ }
19
+ /**
20
+ * A collection's drafts, most recently changed first. `record_id` narrows
21
+ * them to one record, or to several (1 to 100; an empty list is a
22
+ * `TypeError`, since it would match no record).
23
+ */
24
+ list(collection, { record_id, ...params } = {}, options) {
25
+ if (Array.isArray(record_id) && record_id.length === 0)
26
+ throw new TypeError("record_id needs at least one record ID");
27
+ const filter = record_id === undefined
28
+ ? undefined
29
+ : {
30
+ record_id: Array.isArray(record_id) ? { in: record_id } : record_id,
31
+ };
32
+ return this.core.paginate("drafts_list", {
33
+ path: { collection_id: collection },
34
+ query: { ...params, ...(filter && { filter }) },
35
+ }, options);
36
+ }
37
+ /** With `data` as the record reads after the merge, for previews. */
38
+ get(draft, params = {}, options) {
39
+ return this.core.request("drafts_get", { path: { draft_id: draft }, query: params }, options);
40
+ }
41
+ /** Sets the given fields (`null` clears one), as a record update does. */
42
+ update(draft, params, options) {
43
+ return this.core.request("drafts_update", { path: { draft_id: draft }, body: params }, options);
44
+ }
45
+ /** Deletes the draft for good; returns it as it was. */
46
+ discard(draft, options) {
47
+ return this.core.request("drafts_discard", { path: { draft_id: draft } }, options);
48
+ }
49
+ /**
50
+ * Applies the draft to its record now, as one `merge` revision, and
51
+ * returns the record. Content only: the record stays live or not.
52
+ */
53
+ merge(draft, options) {
54
+ return this.core.request("drafts_merge", { path: { draft_id: draft } }, options);
55
+ }
56
+ /** Merges the draft at `merge_at`, a future time; returns the draft. */
57
+ schedule(draft, params, options) {
58
+ return this.core.request("drafts_schedule", { path: { draft_id: draft }, body: params }, options);
59
+ }
60
+ unschedule(draft, options) {
61
+ return this.core.request("drafts_unschedule", { path: { draft_id: draft } }, options);
62
+ }
63
+ }
@@ -3,7 +3,12 @@ import type { RequestOptions } from "../core.ts";
3
3
  import type { AuditEvent, FeatureFlags as FeatureFlagList, Health as HealthStatus, Principal } from "../generated/types.gen.ts";
4
4
  import type { AuditEventListParams } from "../types.ts";
5
5
  import { Resource } from "./resource.ts";
6
- /** The project's activity log, newest first. Needs the `audit:read` scope. */
6
+ /**
7
+ * The project's activity log, newest first. Needs the `audit:read` scope.
8
+ * Filter by `type` (`record.*` for a prefix), `resource_type` (one or
9
+ * several), `resource_id`, `actor_type`, `actor_id` and `created_at`
10
+ * (`{ gte, lt }`).
11
+ */
7
12
  export declare class AuditEvents extends Resource {
8
13
  list(params?: AuditEventListParams, options?: RequestOptions): PagePromise<AuditEvent>;
9
14
  }
@@ -1,8 +1,22 @@
1
1
  import { Resource } from "./resource.js";
2
- /** The project's activity log, newest first. Needs the `audit:read` scope. */
2
+ /**
3
+ * The project's activity log, newest first. Needs the `audit:read` scope.
4
+ * Filter by `type` (`record.*` for a prefix), `resource_type` (one or
5
+ * several), `resource_id`, `actor_type`, `actor_id` and `created_at`
6
+ * (`{ gte, lt }`).
7
+ */
3
8
  export class AuditEvents extends Resource {
4
9
  list(params = {}, options) {
5
- return this.core.paginate("audit_events_list_for_project", { query: params }, options);
10
+ const { filter, ...rest } = params;
11
+ const resourceType = filter?.resource_type;
12
+ return this.core.paginate("audit_events_list", {
13
+ query: {
14
+ ...rest,
15
+ filter: Array.isArray(resourceType)
16
+ ? { ...filter, resource_type: { in: resourceType } }
17
+ : filter,
18
+ },
19
+ }, options);
6
20
  }
7
21
  }
8
22
  export class FeatureFlags extends Resource {
@@ -1,7 +1,7 @@
1
1
  import type { APIPromise, PagePromise } from "../api-promise.ts";
2
- import type { ConditionalRequestOptions, RequestOptions } from "../core.ts";
3
- import type { RecordData, RecordDiff, RecordRevision, RecordRevisionDetail, RevertPreview, BulkRecordsResult, RecordCount } from "../generated/types.gen.ts";
4
- import type { DryRunParams, NoheadRecord, RecordBulkParams, RecordCountParams, RecordCreateParams, RecordDiffParams, RecordGetParams, RecordListParams, RecordScheduleParams, RecordSearchParams, RecordUpdateParams, RevisionListParams, SearchMeta } from "../types.ts";
2
+ import type { ConditionalWriteOptions, RequestOptions, WriteOptions } from "../core.ts";
3
+ import type { RecordData, RecordDiff, RecordRevision, RecordRevisionDetail, RevertPreview, RecordBatch, RecordCount, RecordPublication, RecordSchedule, ScheduledChange } from "../generated/types.gen.ts";
4
+ import type { DryRunParams, NoheadDraft, NoheadRecord, RecordBulkParams, RecordCountParams, RecordCreateParams, RecordDiffParams, RecordGetParams, RecordListParams, RecordScheduleParams, RecordSearchParams, RecordUpdateParams, ListParams, RevisionListParams, ScheduledChangeListParams, SearchMeta } from "../types.ts";
5
5
  import { Resource } from "./resource.ts";
6
6
  /**
7
7
  * Records: the content of a collection. `collection` is a collection ID or
@@ -12,25 +12,54 @@ export declare class Records extends Resource {
12
12
  /** A collection's records, newest first by default. */
13
13
  list<D = RecordData>(collection: string, params?: RecordListParams, options?: RequestOptions): PagePromise<NoheadRecord<D>>;
14
14
  get<D = RecordData>(record: string, params?: RecordGetParams, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
15
- /** Creates a draft. */
16
- create<D = RecordData>(collection: string, params: RecordCreateParams<D>, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
15
+ /** Creates an unpublished record. */
16
+ create<D = RecordData>(collection: string, params: RecordCreateParams<D>, options?: WriteOptions): APIPromise<NoheadRecord<D>>;
17
17
  /** Sets the given fields (`null` clears one); others keep their values. */
18
- update<D = RecordData>(record: string, params: RecordUpdateParams<D>, options?: ConditionalRequestOptions): APIPromise<NoheadRecord<D>>;
19
- /** Soft-deletes the record: `restore` brings it back within 30 days. */
20
- delete<D = RecordData>(record: string, options?: ConditionalRequestOptions): APIPromise<NoheadRecord<D>>;
21
- restore<D = RecordData>(record: string, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
22
- publish<D = RecordData>(record: string, options?: ConditionalRequestOptions): APIPromise<NoheadRecord<D>>;
23
- unpublish<D = RecordData>(record: string, options?: ConditionalRequestOptions): APIPromise<NoheadRecord<D>>;
24
- /** Publishes and/or unpublishes the record later. */
25
- schedule<D = RecordData>(record: string, params: RecordScheduleParams, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
18
+ update<D = RecordData>(record: string, params: RecordUpdateParams<D>, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
19
+ /**
20
+ * Soft-deletes the record: `restore` brings it back until its
21
+ * `purge_after`. Deleting a deleted record changes nothing.
22
+ */
23
+ delete<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
24
+ restore<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
25
+ /**
26
+ * A live record with a pending draft is a `ConflictError` (detail code
27
+ * `draft_pending`): publishing never merges a draft (`drafts.merge` does).
28
+ */
29
+ publish<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
30
+ unpublish<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
31
+ /**
32
+ * What is live: since when, by whom, and the revision. A record that
33
+ * isn't published is a `NotFoundError` (detail code `not_published`).
34
+ */
35
+ publication(record: string, options?: RequestOptions): APIPromise<RecordPublication>;
36
+ /**
37
+ * When the record publishes or unpublishes on its own. One with no
38
+ * schedule is a `NotFoundError` (detail code `not_scheduled`).
39
+ */
40
+ getSchedule(record: string, options?: RequestOptions): APIPromise<RecordSchedule>;
41
+ /** The record's drafts: at most one for now. */
42
+ drafts<D = RecordData>(record: string, params?: ListParams, options?: RequestOptions): PagePromise<NoheadDraft<D>>;
43
+ /**
44
+ * Sets when the record publishes and unpublishes on its own. This is the
45
+ * whole schedule: a time left out is cleared (`{}` clears both, as
46
+ * `unschedule` does).
47
+ */
48
+ schedule(record: string, params: RecordScheduleParams, options?: RequestOptions): APIPromise<RecordSchedule>;
26
49
  /** Clears both scheduled times. */
27
- unschedule<D = RecordData>(record: string, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
50
+ unschedule(record: string, options?: RequestOptions): APIPromise<RecordSchedule>;
51
+ /**
52
+ * A collection's pending scheduled publishes and unpublishes, soonest
53
+ * first: one per change, so a record due to publish and later unpublish
54
+ * appears twice.
55
+ */
56
+ scheduledChanges(collection: string, params?: ScheduledChangeListParams, options?: RequestOptions): PagePromise<ScheduledChange>;
28
57
  count(collection: string, params?: RecordCountParams, options?: RequestOptions): APIPromise<RecordCount>;
29
58
  /**
30
59
  * Publishes, unpublishes, deletes, restores or updates up to 100 records.
31
60
  * Each record succeeds or fails on its own; see `results`.
32
61
  */
33
- bulk(collection: string, params: RecordBulkParams, options?: RequestOptions): APIPromise<BulkRecordsResult>;
62
+ bulk(collection: string, params: RecordBulkParams, options?: WriteOptions): APIPromise<RecordBatch>;
34
63
  /** The changes between two revisions. */
35
64
  diff(record: string, params: RecordDiffParams, options?: RequestOptions): APIPromise<RecordDiff>;
36
65
  /**
@@ -47,6 +76,6 @@ export declare class Revisions extends Resource {
47
76
  /** Restores the record's data as of `revision`, as a new revision. */
48
77
  revert(record: string, revision: number, params: {
49
78
  dry_run: true;
50
- }, options?: ConditionalRequestOptions): APIPromise<RevertPreview>;
51
- revert<D = RecordData>(record: string, revision: number, params?: DryRunParams, options?: ConditionalRequestOptions): APIPromise<NoheadRecord<D>>;
79
+ }, options?: ConditionalWriteOptions): APIPromise<RevertPreview>;
80
+ revert<D = RecordData>(record: string, revision: number, params?: DryRunParams, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
52
81
  }
@@ -12,7 +12,7 @@ export class Records extends Resource {
12
12
  get(record, params = {}, options) {
13
13
  return this.core.request("records_get", { path: { record_id: record }, query: params }, options);
14
14
  }
15
- /** Creates a draft. */
15
+ /** Creates an unpublished record. */
16
16
  create(collection, params, options) {
17
17
  return this.core.request("records_create", { path: { collection_id: collection }, body: params }, options);
18
18
  }
@@ -20,20 +20,49 @@ export class Records extends Resource {
20
20
  update(record, params, options) {
21
21
  return this.core.request("records_update", { path: { record_id: record }, body: params }, options);
22
22
  }
23
- /** Soft-deletes the record: `restore` brings it back within 30 days. */
23
+ /**
24
+ * Soft-deletes the record: `restore` brings it back until its
25
+ * `purge_after`. Deleting a deleted record changes nothing.
26
+ */
24
27
  delete(record, options) {
25
28
  return this.core.request("records_delete", { path: { record_id: record } }, options);
26
29
  }
27
30
  restore(record, options) {
28
31
  return this.core.request("records_restore", { path: { record_id: record } }, options);
29
32
  }
33
+ /**
34
+ * A live record with a pending draft is a `ConflictError` (detail code
35
+ * `draft_pending`): publishing never merges a draft (`drafts.merge` does).
36
+ */
30
37
  publish(record, options) {
31
38
  return this.core.request("records_publish", { path: { record_id: record } }, options);
32
39
  }
33
40
  unpublish(record, options) {
34
41
  return this.core.request("records_unpublish", { path: { record_id: record } }, options);
35
42
  }
36
- /** Publishes and/or unpublishes the record later. */
43
+ /**
44
+ * What is live: since when, by whom, and the revision. A record that
45
+ * isn't published is a `NotFoundError` (detail code `not_published`).
46
+ */
47
+ publication(record, options) {
48
+ return this.core.request("records_get_publication", { path: { record_id: record } }, options);
49
+ }
50
+ /**
51
+ * When the record publishes or unpublishes on its own. One with no
52
+ * schedule is a `NotFoundError` (detail code `not_scheduled`).
53
+ */
54
+ getSchedule(record, options) {
55
+ return this.core.request("records_get_schedule", { path: { record_id: record } }, options);
56
+ }
57
+ /** The record's drafts: at most one for now. */
58
+ drafts(record, params = {}, options) {
59
+ return this.core.paginate("record_drafts_list", { path: { record_id: record }, query: params }, options);
60
+ }
61
+ /**
62
+ * Sets when the record publishes and unpublishes on its own. This is the
63
+ * whole schedule: a time left out is cleared (`{}` clears both, as
64
+ * `unschedule` does).
65
+ */
37
66
  schedule(record, params, options) {
38
67
  return this.core.request("records_schedule", { path: { record_id: record }, body: params }, options);
39
68
  }
@@ -41,6 +70,14 @@ export class Records extends Resource {
41
70
  unschedule(record, options) {
42
71
  return this.core.request("records_unschedule", { path: { record_id: record } }, options);
43
72
  }
73
+ /**
74
+ * A collection's pending scheduled publishes and unpublishes, soonest
75
+ * first: one per change, so a record due to publish and later unpublish
76
+ * appears twice.
77
+ */
78
+ scheduledChanges(collection, params = {}, options) {
79
+ return this.core.paginate("scheduled_changes_list", { path: { collection_id: collection }, query: params }, options);
80
+ }
44
81
  count(collection, params = {}, options) {
45
82
  return this.core.request("records_count", { path: { collection_id: collection }, query: params }, options);
46
83
  }
@@ -3,3 +3,8 @@ export declare abstract class Resource {
3
3
  protected readonly core: Core;
4
4
  constructor(core: Core);
5
5
  }
6
+ /**
7
+ * A list's query: the options the API reads as filters (`deleted`,
8
+ * `content_type`, `status`) go under `filter[...]`, the rest stay as they are.
9
+ */
10
+ export declare function listQuery(params: object, filters: readonly string[]): Record<string, unknown>;
@@ -4,3 +4,17 @@ export class Resource {
4
4
  this.core = core;
5
5
  }
6
6
  }
7
+ /**
8
+ * A list's query: the options the API reads as filters (`deleted`,
9
+ * `content_type`, `status`) go under `filter[...]`, the rest stay as they are.
10
+ */
11
+ export function listQuery(params, filters) {
12
+ const query = { ...params };
13
+ const filter = {};
14
+ for (const name of filters) {
15
+ if (query[name] !== undefined)
16
+ filter[name] = query[name];
17
+ delete query[name];
18
+ }
19
+ return Object.keys(filter).length > 0 ? { ...query, filter } : query;
20
+ }
@@ -1,7 +1,7 @@
1
1
  import type { APIPromise, PagePromise } from "../api-promise.ts";
2
- import type { RequestOptions } from "../core.ts";
3
- import type { Collection, CollectionCreate, CollectionUpdate, Field, FieldCreate, FieldMigration, FieldMigrationPreview, FieldUpdate, Schema, SchemaChange, SchemaChangeDetail, SearchIndex } from "../generated/types.gen.ts";
4
- import type { DeletedListParams, DryRunParams, FieldMigrateParams, ListParams, SchemaParams } from "../types.ts";
2
+ import type { RequestOptions, WriteOptions } from "../core.ts";
3
+ import type { Collection, FieldOrder, CollectionCreate, CollectionUpdate, Field, FieldCreate, FieldMigration, FieldMigrationPreview, FieldUpdate, Schema, SchemaChange, SchemaChangeDetail, SearchIndex } from "../generated/types.gen.ts";
4
+ import type { DeletedListParams, DryRunParams, FieldMigrateParams, FieldReorderParams, ListParams, SchemaParams } from "../types.ts";
5
5
  import { Resource } from "./resource.ts";
6
6
  /** Collections of the key's project. `collection` is an ID or slug. */
7
7
  export declare class Collections extends Resource {
@@ -10,11 +10,14 @@ export declare class Collections extends Resource {
10
10
  list(params?: DeletedListParams, options?: RequestOptions): PagePromise<Collection>;
11
11
  get(collection: string, options?: RequestOptions): APIPromise<Collection>;
12
12
  /** Creates a collection, optionally with its fields. */
13
- create(params: CollectionCreate, options?: RequestOptions): APIPromise<Collection>;
14
- update(collection: string, params: CollectionUpdate, options?: RequestOptions): APIPromise<Collection>;
15
- /** Soft-deletes the collection and its records for 30 days. */
16
- delete(collection: string, options?: RequestOptions): APIPromise<Collection>;
17
- restore(collection: string, options?: RequestOptions): APIPromise<Collection>;
13
+ create(params: CollectionCreate, options?: WriteOptions): APIPromise<Collection>;
14
+ update(collection: string, params: CollectionUpdate, options?: WriteOptions): APIPromise<Collection>;
15
+ /**
16
+ * Soft-deletes the collection and its records: `restore` brings them back
17
+ * until its `purge_after`.
18
+ */
19
+ delete(collection: string, options?: WriteOptions): APIPromise<Collection>;
20
+ restore(collection: string, options?: WriteOptions): APIPromise<Collection>;
18
21
  /** The collection's schema, now or at a past `version`. */
19
22
  schema(collection: string, params?: SchemaParams, options?: RequestOptions): APIPromise<Schema>;
20
23
  }
@@ -32,19 +35,23 @@ export declare class SearchIndexes extends Resource {
32
35
  /** Fields of a collection. `field` is a field ID (`fld_…`). */
33
36
  export declare class Fields extends Resource {
34
37
  list(collection: string, params?: DeletedListParams, options?: RequestOptions): PagePromise<Field>;
35
- create(collection: string, params: FieldCreate, options?: RequestOptions): APIPromise<Field>;
38
+ create(collection: string, params: FieldCreate, options?: WriteOptions): APIPromise<Field>;
39
+ get(field: string, options?: RequestOptions): APIPromise<Field>;
36
40
  /**
37
41
  * Renames, describes or loosens a field. Changes that rewrite record
38
42
  * values (type, `multiple`, tighter rules) are `migrate`.
39
43
  */
40
- update(field: string, params: FieldUpdate, options?: RequestOptions): APIPromise<Field>;
41
- /** Soft-deletes the field: its values return with `restore` for 30 days. */
42
- delete(field: string, options?: RequestOptions): APIPromise<Field>;
43
- restore(field: string, options?: RequestOptions): APIPromise<Field>;
44
- /** Puts the collection's fields in this order. */
45
- reorder(collection: string, params: {
46
- field_ids: string[];
47
- }, options?: RequestOptions): APIPromise<Collection>;
44
+ update(field: string, params: FieldUpdate, options?: WriteOptions): APIPromise<Field>;
45
+ /**
46
+ * Soft-deletes the field: its values come back with `restore` until its
47
+ * `purge_after`.
48
+ */
49
+ delete(field: string, options?: WriteOptions): APIPromise<Field>;
50
+ restore(field: string, options?: WriteOptions): APIPromise<Field>;
51
+ /** The collection's active fields, in order. */
52
+ order(collection: string, options?: RequestOptions): APIPromise<FieldOrder>;
53
+ /** Puts the collection's fields in this order; lists every active field once. */
54
+ reorder(collection: string, params: FieldReorderParams, options?: WriteOptions): APIPromise<FieldOrder>;
48
55
  /** Stops accepting a renamed field's old API key before its 6 months end. */
49
56
  removeAlias(field: string, alias: string, options?: RequestOptions): APIPromise<Field>;
50
57
  /**
@@ -53,8 +60,8 @@ export declare class Fields extends Resource {
53
60
  */
54
61
  migrate(field: string, params: FieldMigrateParams & {
55
62
  dry_run: true;
56
- }, options?: RequestOptions): APIPromise<FieldMigrationPreview>;
57
- migrate(field: string, params: FieldMigrateParams & DryRunParams, options?: RequestOptions): APIPromise<FieldMigration>;
63
+ }, options?: WriteOptions): APIPromise<FieldMigrationPreview>;
64
+ migrate(field: string, params: FieldMigrateParams & DryRunParams, options?: WriteOptions): APIPromise<FieldMigration>;
58
65
  }
59
66
  /** Field migrations. While one runs, its collection is read-only. */
60
67
  export declare class Migrations extends Resource {