@nohead/sdk 0.8.0 → 0.10.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.
@@ -1,5 +1,5 @@
1
1
  import type { APIPromise, PagePromise } from "../api-promise.ts";
2
- import type { ConditionalRequestOptions, ConditionalWriteOptions, RequestOptions } from "../core.ts";
2
+ import type { ConditionalRequestOptions, ConditionalWriteOptions, RichTextOptions } from "../core.ts";
3
3
  import type { RecordData } from "../generated/types.gen.ts";
4
4
  import type { DraftCreateParams, DraftGetParams, DraftListParams, DraftScheduleParams, DraftUpdateParams, NoheadDraft, NoheadRecord } from "../types.ts";
5
5
  import { Resource } from "./resource.ts";
@@ -17,24 +17,24 @@ export declare class Drafts extends Resource {
17
17
  * `ConflictError` (detail code `draft_exists`, with its `draft_id`): update
18
18
  * that one instead.
19
19
  */
20
- create<D = RecordData>(record: string, params?: DraftCreateParams<D>, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
20
+ create<D = RecordData>(record: string, params?: DraftCreateParams<D>, options?: RichTextOptions): APIPromise<NoheadDraft<D>>;
21
21
  /**
22
22
  * A collection's drafts, most recently changed first. One record's draft
23
23
  * is `records.drafts(record)`.
24
24
  */
25
- list<D = RecordData>(collection: string, params?: DraftListParams, options?: RequestOptions): PagePromise<NoheadDraft<D>>;
25
+ list<D = RecordData>(collection: string, params?: DraftListParams, options?: RichTextOptions): PagePromise<NoheadDraft<D>>;
26
26
  /** With `data` as the record reads after the merge, for previews. */
27
- get<D = RecordData>(draft: string, params?: DraftGetParams, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
27
+ get<D = RecordData>(draft: string, params?: DraftGetParams, options?: RichTextOptions): APIPromise<NoheadDraft<D>>;
28
28
  /** Sets the given fields (`null` clears one), as a record update does. */
29
- update<D = RecordData>(draft: string, params: DraftUpdateParams<D>, options?: ConditionalRequestOptions): APIPromise<NoheadDraft<D>>;
29
+ update<D = RecordData>(draft: string, params: DraftUpdateParams<D>, options?: ConditionalRequestOptions & RichTextOptions): APIPromise<NoheadDraft<D>>;
30
30
  /** Deletes the draft for good; returns it as it was. */
31
- discard<D = RecordData>(draft: string, options?: ConditionalRequestOptions): APIPromise<NoheadDraft<D>>;
31
+ discard<D = RecordData>(draft: string, options?: ConditionalRequestOptions & RichTextOptions): APIPromise<NoheadDraft<D>>;
32
32
  /**
33
33
  * Applies the draft to its record now, as one `merge` revision, and
34
34
  * returns the record. Content only: the record stays live or not.
35
35
  */
36
- merge<D = RecordData>(draft: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
36
+ merge<D = RecordData>(draft: string, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
37
37
  /** Merges the draft at `merge_at`, a future time; returns the draft. */
38
- schedule<D = RecordData>(draft: string, params: DraftScheduleParams, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
39
- unschedule<D = RecordData>(draft: string, options?: RequestOptions): APIPromise<NoheadDraft<D>>;
38
+ schedule<D = RecordData>(draft: string, params: DraftScheduleParams, options?: RichTextOptions): APIPromise<NoheadDraft<D>>;
39
+ unschedule<D = RecordData>(draft: string, options?: RichTextOptions): APIPromise<NoheadDraft<D>>;
40
40
  }
@@ -1,5 +1,5 @@
1
1
  import type { APIPromise, PagePromise } from "../api-promise.ts";
2
- import type { ConditionalWriteOptions, RequestOptions, WriteOptions } from "../core.ts";
2
+ import type { ConditionalWriteOptions, RequestOptions, RichTextOptions, WriteOptions } from "../core.ts";
3
3
  import type { RecordData, RecordDiff, RecordRevision, RecordRevisionDetail, RevertPreview, RecordBatch, RecordCount, RecordPublication, RecordSchedule, ScheduledChange } from "../generated/types.gen.ts";
4
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";
@@ -10,28 +10,28 @@ import { Resource } from "./resource.ts";
10
10
  export declare class Records extends Resource {
11
11
  readonly revisions: Revisions;
12
12
  /** A collection's records, newest first by default. */
13
- list<D = RecordData>(collection: string, params?: RecordListParams, options?: RequestOptions): PagePromise<NoheadRecord<D>>;
14
- get<D = RecordData>(record: string, params?: RecordGetParams, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
13
+ list<D = RecordData>(collection: string, params?: RecordListParams, options?: RichTextOptions): PagePromise<NoheadRecord<D>>;
14
+ get<D = RecordData>(record: string, params?: RecordGetParams, options?: RichTextOptions): APIPromise<NoheadRecord<D>>;
15
15
  /**
16
16
  * Creates an unpublished record. With `upsert_on`, updates the record
17
17
  * holding that unique value instead, if one exists, so a sync can run
18
18
  * again without duplicates; `ifMatch` then applies to that update.
19
19
  */
20
- create<D = RecordData>(collection: string, params: RecordCreateParams<D>, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
20
+ create<D = RecordData>(collection: string, params: RecordCreateParams<D>, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
21
21
  /** Sets the given fields (`null` clears one); others keep their values. */
22
- update<D = RecordData>(record: string, params: RecordUpdateParams<D>, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
22
+ update<D = RecordData>(record: string, params: RecordUpdateParams<D>, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
23
23
  /**
24
24
  * Soft-deletes the record: `restore` brings it back until its
25
25
  * `purge_after`. Deleting a deleted record changes nothing.
26
26
  */
27
- delete<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
28
- restore<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
27
+ delete<D = RecordData>(record: string, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
28
+ restore<D = RecordData>(record: string, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
29
29
  /**
30
30
  * A live record with a pending draft is a `ConflictError` (detail code
31
31
  * `draft_pending`): publishing never merges a draft (`drafts.merge` does).
32
32
  */
33
- publish<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
34
- unpublish<D = RecordData>(record: string, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
33
+ publish<D = RecordData>(record: string, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
34
+ unpublish<D = RecordData>(record: string, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
35
35
  /**
36
36
  * What is live: since when, by whom, and the revision. A record that
37
37
  * isn't published is a `NotFoundError` (detail code `not_published`).
@@ -43,7 +43,7 @@ export declare class Records extends Resource {
43
43
  */
44
44
  getSchedule(record: string, options?: RequestOptions): APIPromise<RecordSchedule>;
45
45
  /** The record's drafts: at most one for now. */
46
- drafts<D = RecordData>(record: string, params?: ListParams, options?: RequestOptions): PagePromise<NoheadDraft<D>>;
46
+ drafts<D = RecordData>(record: string, params?: ListParams, options?: RichTextOptions): PagePromise<NoheadDraft<D>>;
47
47
  /**
48
48
  * Sets when the record publishes and unpublishes on its own. This is the
49
49
  * whole schedule: a time left out is cleared (`{}` clears both, as
@@ -63,14 +63,14 @@ export declare class Records extends Resource {
63
63
  * Publishes, unpublishes, deletes, restores or updates up to 100 records.
64
64
  * Each record succeeds or fails on its own; see `results`.
65
65
  */
66
- bulk(collection: string, params: RecordBulkParams, options?: WriteOptions): APIPromise<RecordBatch>;
66
+ bulk(collection: string, params: RecordBulkParams, options?: WriteOptions & RichTextOptions): APIPromise<RecordBatch>;
67
67
  /** The changes between two revisions. */
68
68
  diff(record: string, params: RecordDiffParams, options?: RequestOptions): APIPromise<RecordDiff>;
69
69
  /**
70
70
  * Full-text search in one collection, matching its `searchable` fields.
71
71
  * Pages through the first 1,000 hits, most relevant first.
72
72
  */
73
- search<D = RecordData>(collection: string, query: string, params?: RecordSearchParams, options?: RequestOptions): PagePromise<NoheadRecord<D>, SearchMeta>;
73
+ search<D = RecordData>(collection: string, query: string, params?: RecordSearchParams, options?: RichTextOptions): PagePromise<NoheadRecord<D>, SearchMeta>;
74
74
  }
75
75
  /** A record's version history. `revision` is a revision number. */
76
76
  export declare class Revisions extends Resource {
@@ -80,8 +80,8 @@ export declare class Revisions extends Resource {
80
80
  /** Restores the record's data as of `revision`, as a new revision. */
81
81
  revert(record: string, revision: number, params: {
82
82
  dry_run: true;
83
- }, options?: ConditionalWriteOptions): APIPromise<RevertPreview>;
84
- revert<D = RecordData>(record: string, revision: number, params?: DryRunParams, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
83
+ }, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<RevertPreview>;
84
+ revert<D = RecordData>(record: string, revision: number, params?: DryRunParams, options?: ConditionalWriteOptions & RichTextOptions): APIPromise<NoheadRecord<D>>;
85
85
  }
86
86
  /**
87
87
  * A revision by its own ID (`rev_…`), as webhooks and the activity log name
package/dist/types.d.ts CHANGED
@@ -21,6 +21,13 @@ export type NoheadDraft<D = G.RecordData> = Omit<G.Draft, "data"> & {
21
21
  export type RecordDataUpdate<D> = {
22
22
  [K in keyof D]?: D[K] | null;
23
23
  };
24
+ /**
25
+ * How rich text fields read (`richText`): `"document"`, the stored
26
+ * ProseMirror JSON document (the default); `"html"`, an HTML fragment safe
27
+ * to put in a page as it is; or `"markdown"` (GitHub Flavored). As HTML or
28
+ * Markdown, a rich text field's value is a string.
29
+ */
30
+ export type RichText = G.RichText;
24
31
  export type FilterValue = string | number | boolean | Date;
25
32
  /**
26
33
  * Operators for one key. `ne` matches records without a value; on fields
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.8.0";
1
+ export declare const VERSION = "0.10.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.8.0";
1
+ export const VERSION = "0.10.0";
@@ -49,8 +49,9 @@ export interface UnwrapOptions {
49
49
  /**
50
50
  * The webhook's signing secret (`whsec_…`). While a rotation overlaps,
51
51
  * requests carry a signature for each secret, so either one verifies.
52
+ * An unset one (as from a missing environment variable) throws.
52
53
  */
53
- secret: string;
54
+ secret: string | undefined;
54
55
  /** Seconds a timestamp may be off from now. Default 300. */
55
56
  tolerance?: number;
56
57
  }
package/dist/webhooks.js CHANGED
@@ -24,7 +24,11 @@ export async function unwrapWebhook(body, headers, { secret, tolerance = 300 })
24
24
  throw new WebhookVerificationError("The webhook timestamp is too far from the current time");
25
25
  }
26
26
  const text = typeof body === "string" ? body : new TextDecoder().decode(body);
27
- const key = await crypto.subtle.importKey("raw", decodeBase64(secret.replace(/^whsec_/, ""), "secret"), { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
27
+ const keyBytes = decodeBase64((secret ?? "").replace(/^whsec_/, ""), "secret");
28
+ if (keyBytes.length === 0) {
29
+ throw new WebhookVerificationError("The webhook secret is empty");
30
+ }
31
+ const key = await crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
28
32
  const signed = new TextEncoder().encode(`${id}.${timestamp}.${text}`);
29
33
  for (const entry of signatures.split(" ")) {
30
34
  const [version, signature] = entry.split(",", 2);
@@ -63,8 +67,5 @@ function decodeBase64(value, what) {
63
67
  catch {
64
68
  throw new WebhookVerificationError(`The webhook ${what} is not base64`);
65
69
  }
66
- const bytes = new Uint8Array(binary.length);
67
- for (let i = 0; i < binary.length; i++)
68
- bytes[i] = binary.charCodeAt(i);
69
- return bytes;
70
+ return Uint8Array.from(binary, (char) => char.charCodeAt(0));
70
71
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nohead/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Official TypeScript SDK for the Nohead API",
5
5
  "license": "MIT",
6
6
  "homepage": "https://nohead.io",
@@ -61,6 +61,7 @@
61
61
  "eslint": "^10.12.0",
62
62
  "globals": "^17.13.0",
63
63
  "prettier": "^3.9.9",
64
+ "standardwebhooks": "^1.1.1",
64
65
  "typescript": "^6.0.3",
65
66
  "typescript-eslint": "^8.71.0",
66
67
  "vitest": "^5.0.3"