@andesine/sdk 0.1.0 → 0.4.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/CHANGELOG.md +31 -0
- package/README.md +263 -29
- package/WEBHOOKS.md +317 -0
- package/dist/THIRD_PARTY_LICENSES.txt +49 -0
- package/dist/content-slug-C7CgtHmp.d.ts +13 -0
- package/dist/content-slug.d.ts +2 -0
- package/dist/content-slug.js +19 -0
- package/dist/content-slug.js.map +1 -0
- package/dist/index-moj3WP71.d.ts +1982 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +240 -14
- package/dist/index.js.map +1 -1
- package/dist/rolldown-runtime-EAsCxrDo.js +14 -0
- package/dist/{index-DFEcYmbh.d.ts → schema-BcVop8NH.d.ts} +10489 -6241
- package/dist/streaming.d.ts +1 -1
- package/dist/webhooks.d.ts +26 -0
- package/dist/webhooks.js +7429 -0
- package/dist/webhooks.js.map +1 -0
- package/openapi.json +13163 -4665
- package/package.json +14 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
- Document the limits: per-minute rate limits, the monthly API call and AI credit
|
|
6
|
+
meters, the Pro spending limit, the `X-RateLimit-*`, `X-API-Usage*`, and
|
|
7
|
+
`X-AI-Credits*` headers, and the new `limit` field of `TOO_MANY_REQUESTS` error
|
|
8
|
+
data (`rate`, `api-calls`, `ai-credits`, or `spending`). `X-RateLimit-*` now
|
|
9
|
+
describes the rate limit, not the monthly usage.
|
|
10
|
+
|
|
11
|
+
- Document publishable keys (`adn_pk_...`) for browser use: published content
|
|
12
|
+
reads, search, and answers from the key's collections and origins, and server
|
|
13
|
+
reads without an `Origin`, e.g. site builds.
|
|
14
|
+
|
|
15
|
+
## 0.3.0
|
|
16
|
+
|
|
17
|
+
- Add generated webhook methods for management (including bulk enable/disable and
|
|
18
|
+
delete), delivery history, signed tests, and single or bulk replay, plus public
|
|
19
|
+
webhook event types.
|
|
20
|
+
- Add the isolated `@andesine/sdk/webhooks` verifier with raw-body authentication,
|
|
21
|
+
timestamp and schema checks, plus receiver and durable deduplication examples.
|
|
22
|
+
|
|
23
|
+
## 0.2.0
|
|
24
|
+
|
|
25
|
+
- Add derived `slugPath` selectors and responses, slug-based sibling uniqueness,
|
|
26
|
+
slug-aware workspace maps, and slug URLs by default in `toContentURL`.
|
|
27
|
+
|
|
28
|
+
- Add type-only workspace maps through `createClient<Workspace>()`, with selector-aware
|
|
29
|
+
content types, revision unions, optional entry/tree bindings, and typed content helpers.
|
|
30
|
+
- Add bulk current/published type metadata with effective schema revisions,
|
|
31
|
+
optional entries/tree, consistent source reads, and stable fingerprints.
|
|
32
|
+
- Explicit OAuth access tokens without API-key environment fallback, plus credential identity and user workspace discovery.
|
|
33
|
+
|
|
3
34
|
## 0.1.0
|
|
4
35
|
|
|
5
36
|
- Initial public TypeScript client generated from the Andesine OpenAPI document.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MIT-licensed TypeScript client for the public Andesine HTTP API. ESM only. Requires
|
|
4
4
|
Node.js 22 or later, or a browser/worker runtime with Fetch, Blob, FormData, and
|
|
5
|
-
AbortSignal.any. Keep
|
|
5
|
+
AbortSignal.any. Keep secret API keys in server code; browsers use publishable keys.
|
|
6
6
|
|
|
7
7
|
## Use
|
|
8
8
|
|
|
@@ -25,13 +25,51 @@ const published = await client.content.get({
|
|
|
25
25
|
});
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
`baseURL`
|
|
28
|
+
`baseURL` defaults to `https://api.andesine.app`. A trailing slash is optional; path prefixes are preserved.
|
|
29
29
|
Each client has its own configuration. You can supply `fetch` and default
|
|
30
30
|
`headers` for proxies, instrumentation, or other authentication arrangements.
|
|
31
31
|
|
|
32
|
+
For OAuth credentials, use `accessToken` instead of `apiKey`. This disables the
|
|
33
|
+
`ANDESINE_API_KEY` fallback. The SDK does not log in or refresh tokens.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
const client = createClient({ accessToken });
|
|
37
|
+
const identity = await client.auth.getIdentity();
|
|
38
|
+
const workspaces = await client.workspaces.list();
|
|
39
|
+
const workspaceClient = createClient({
|
|
40
|
+
accessToken,
|
|
41
|
+
headers: { "x-workspace-id": selectedWorkspaceID }
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Publishable keys
|
|
46
|
+
|
|
47
|
+
Publishable keys (`adn_pk_...`) are safe in browsers. Create one in the Andesine
|
|
48
|
+
app, with its collections and the origins of the sites that use it. A publishable
|
|
49
|
+
key can read the published content of its collections (`content.getTree`,
|
|
50
|
+
`content.get`, `content.listEntries`), search it (`search.published`), and, when
|
|
51
|
+
the key allows it, answer questions about it (`search.askPublished` and
|
|
52
|
+
`search.askPublishedStream`). Browser requests need an allowed `Origin`, so the key
|
|
53
|
+
works only on its sites; requests without `Origin`, e.g. from a site build on a
|
|
54
|
+
server, are allowed. Other operations are refused.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
const client = createClient({ apiKey: "adn_pk_..." });
|
|
58
|
+
const results = await client.search.published({ query: "install", channel: "published" });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Pass the key as `apiKey`. This also disables the `ANDESINE_API_KEY` fallback, so a
|
|
62
|
+
bundler that defines `process.env` cannot add a secret key to browser code. The key
|
|
63
|
+
has the same rate limits and usage quota as other API access, and all visitors of a
|
|
64
|
+
site share them.
|
|
65
|
+
|
|
66
|
+
Select a workspace explicitly for OAuth workspace operations. The server checks
|
|
67
|
+
current user permissions on each request. Browser-only operations remain excluded.
|
|
68
|
+
API keys keep their workspace binding and cannot list a user's workspaces.
|
|
69
|
+
|
|
32
70
|
Resource methods are generated from the checked-in OpenAPI document. They cover
|
|
33
71
|
assets, entries, collections, content delivery, roles, search, schemas, schema
|
|
34
|
-
migrations, schema versions, memberships, publishing, entry versions, and instance information. Internal
|
|
72
|
+
migrations, schema versions, memberships, publishing, entry versions, webhooks, and instance information. Internal
|
|
35
73
|
session-only operations are excluded. Published asset delivery does not require
|
|
36
74
|
an API key.
|
|
37
75
|
|
|
@@ -68,7 +106,7 @@ try {
|
|
|
68
106
|
}
|
|
69
107
|
|
|
70
108
|
if (error.is("TOO_MANY_REQUESTS")) {
|
|
71
|
-
console.log(error.data?.retryAfterSeconds);
|
|
109
|
+
console.log(error.data?.limit, error.data?.retryAfterSeconds);
|
|
72
110
|
}
|
|
73
111
|
}
|
|
74
112
|
}
|
|
@@ -89,6 +127,48 @@ Use full-response mode for conditional requests. A 304 response has
|
|
|
89
127
|
`notModified: true` and no data. A 304 in data mode causes a clear error because
|
|
90
128
|
the client does not store a response cache.
|
|
91
129
|
|
|
130
|
+
## Limits and usage
|
|
131
|
+
|
|
132
|
+
Rate limits stop abuse; they count requests for each credential (API key, OAuth
|
|
133
|
+
grant, or app session) in one-minute windows.
|
|
134
|
+
|
|
135
|
+
| Requests a minute | Free | Pro |
|
|
136
|
+
| --------------------------------- | ---- | ----- |
|
|
137
|
+
| All requests | 600 | 6,000 |
|
|
138
|
+
| AI answers | 60 | 600 |
|
|
139
|
+
| Semantic search (with `semantic`) | 300 | 3,000 |
|
|
140
|
+
|
|
141
|
+
Each workspace also has two monthly meters, which reset at 00:00 UTC on the first
|
|
142
|
+
day of each month:
|
|
143
|
+
|
|
144
|
+
- **API calls:** each request with an API key or OAuth. Free includes 50,000; Pro
|
|
145
|
+
includes 500,000 and bills the rest.
|
|
146
|
+
- **AI credits:** an AI answer uses 3 credits, and a semantic search uses 1. Requests
|
|
147
|
+
from the app use credits too. Free includes 5,000; Pro includes 50,000 and bills
|
|
148
|
+
the rest.
|
|
149
|
+
|
|
150
|
+
On Free, the meters are hard limits. On Pro, a workspace admin can set a monthly
|
|
151
|
+
spending limit for the billed usage; when it is reached, metered requests stop until
|
|
152
|
+
the next month.
|
|
153
|
+
|
|
154
|
+
Every limit returns `TOO_MANY_REQUESTS` with `data.limit` (`rate`, `api-calls`,
|
|
155
|
+
`ai-credits`, or `spending`) and `data.retryAfterSeconds`, also sent as
|
|
156
|
+
`Retry-After`. A `rate` limit passes within a minute; the others last until the
|
|
157
|
+
monthly reset, so do not retry them automatically.
|
|
158
|
+
|
|
159
|
+
Responses describe the limits in headers:
|
|
160
|
+
|
|
161
|
+
- `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`: the rate
|
|
162
|
+
limit that applies to the request; AI requests show their AI limit.
|
|
163
|
+
- `X-API-Usage`, `X-API-Usage-Limit`, and `X-API-Usage-Reset`: the month's API calls,
|
|
164
|
+
on metered requests.
|
|
165
|
+
- `X-AI-Credits`, `X-AI-Credits-Limit`, and `X-AI-Credits-Reset`: the month's AI
|
|
166
|
+
credits, on AI requests.
|
|
167
|
+
|
|
168
|
+
Limits are the hard limit on Free, or the included amount on Pro. Reset values are
|
|
169
|
+
Unix times in seconds. Self-hosted instances without billing have the Pro rate limits
|
|
170
|
+
and no meters.
|
|
171
|
+
|
|
92
172
|
## Cancellation, timeouts, and retries
|
|
93
173
|
|
|
94
174
|
The default timeout is 30 seconds. Set `timeout: 0` to disable it. Timeouts include
|
|
@@ -361,9 +441,8 @@ public package imports the private editor or backend at runtime.
|
|
|
361
441
|
From the repository root:
|
|
362
442
|
|
|
363
443
|
```sh
|
|
364
|
-
pnpm
|
|
365
|
-
pnpm --filter
|
|
366
|
-
pnpm --filter @andesine/sdk build
|
|
444
|
+
pnpm api:generate
|
|
445
|
+
pnpm build --filter=@andesine/sdk
|
|
367
446
|
```
|
|
368
447
|
|
|
369
448
|
The export calls oRPC's OpenAPI generator on the same contracts implemented by
|
|
@@ -403,7 +482,8 @@ keeps runtime dependencies small.
|
|
|
403
482
|
## Content names
|
|
404
483
|
|
|
405
484
|
Sibling entries and collections share names. Names are trimmed, normalized to
|
|
406
|
-
Unicode NFC, and
|
|
485
|
+
Unicode NFC, and must have unique derived URL slugs at each level. Exact names
|
|
486
|
+
also remain unique, including symbol-only names. Names cannot contain `/` or equal
|
|
407
487
|
`.` or `..`. The limit is 300 JavaScript string units. The collection name `~`
|
|
408
488
|
is reserved for the internal workspace root. Root entries and root collections
|
|
409
489
|
share the same level.
|
|
@@ -413,20 +493,20 @@ Use the returned name rather than assuming that your requested name was saved.
|
|
|
413
493
|
Rename, move, and restore operations reject conflicts. Deleted items release
|
|
414
494
|
names; a schema move temporarily reserves its source name for rollback.
|
|
415
495
|
|
|
416
|
-
`CONTENT_NAME_CONFLICT` (409) includes `name`, `parentID`, and optional `hints`.
|
|
496
|
+
`CONTENT_NAME_CONFLICT` (409) includes `name`, `slug`, `parentID`, and optional `hints`.
|
|
417
497
|
Use `error.is("CONTENT_NAME_CONFLICT")` to access typed data. Renaming never
|
|
418
498
|
chooses a different name for you.
|
|
419
499
|
|
|
420
500
|
## Content paths
|
|
421
501
|
|
|
422
|
-
Read an entry by ID or
|
|
502
|
+
Read an entry by ID, `path`, or `slugPath`. Use exactly one selector:
|
|
423
503
|
|
|
424
504
|
```ts
|
|
425
505
|
const current = await client.entries.get({ path: "/Docs/Getting started" });
|
|
426
|
-
const tree = await client.content.getTree({
|
|
506
|
+
const tree = await client.content.getTree({ collectionSlugPath: "/docs" });
|
|
427
507
|
const content = client.atSnapshot(tree.snapshotID);
|
|
428
|
-
const page = await content.get({
|
|
429
|
-
const definition = await content.getSchema({
|
|
508
|
+
const page = await content.get({ slugPath: "/docs/getting-started" });
|
|
509
|
+
const definition = await content.getSchema({ slugPath: page.slugPath });
|
|
430
510
|
const activeSchema = await client.schemas.get({ collectionPath: "/Docs" });
|
|
431
511
|
```
|
|
432
512
|
|
|
@@ -441,23 +521,56 @@ selected current tree or snapshot. A name that looks like an ID is still a name
|
|
|
441
521
|
when it occurs in an absolute path. A bare collection ID is also a valid
|
|
442
522
|
`collectionPath`. `/` selects the root. Neither selects an entry on its own.
|
|
443
523
|
|
|
444
|
-
Current entry and collection responses include their canonical absolute `path`.
|
|
524
|
+
Current entry and collection responses include their canonical absolute `path` and `slugPath`.
|
|
445
525
|
Published content, trees, and list results use snapshot collection names and the
|
|
446
526
|
titles of assigned versions. Draft renames, moves, and deletions do not change
|
|
447
527
|
those snapshot paths. Full published content also includes `id` and `collectionID`.
|
|
448
528
|
Saved versions remain ID-based because a version alone has no snapshot location.
|
|
449
529
|
|
|
450
530
|
`content.getTree({ collectionPath: "/" })` returns a virtual root collection with
|
|
451
|
-
`id: null`, `name: ""`, and `
|
|
531
|
+
`id: null`, `name: ""`, `path: "/"`, and `slugPath: "/"`. It contains top-level entries and collections.
|
|
452
532
|
|
|
453
533
|
`entries.list`, `collections.list`, `content.listEntries`, and
|
|
454
|
-
`content.listCollections` accept
|
|
534
|
+
`content.listCollections` accept one of `collectionID`, `collectionPath`, or `collectionSlugPath` to
|
|
455
535
|
select direct children. Keep the same scope while paging. With no scope,
|
|
456
536
|
`collections.list` selects root children; the other lists select all accessible
|
|
457
537
|
items. `collections.list` now uses these fields instead of `ancestorID`.
|
|
458
538
|
Search accepts the same collection selectors and includes descendants. Its `/`
|
|
459
539
|
scope covers the whole accessible tree. Search results include a canonical entry
|
|
460
|
-
`path` and an optional heading `anchor`.
|
|
540
|
+
`path`, `slugPath`, and an optional heading `anchor`.
|
|
541
|
+
|
|
542
|
+
Slugs use Unicode NFKC normalization, lowercase, Unicode letters/marks/numbers,
|
|
543
|
+
and single hyphens between other character groups. Accents and non-Latin letters
|
|
544
|
+
are retained. A symbol-only name uses its public ID in lowercase with `-` instead
|
|
545
|
+
of `_`. Slugs are derived, never edited separately. Renaming or moving content
|
|
546
|
+
changes its path; redirects are not stored. `Getting Started`, `getting-started`,
|
|
547
|
+
and `Getting Started!` conflict at the same level. Existing conflicting content
|
|
548
|
+
must be renamed before publishing it again.
|
|
549
|
+
|
|
550
|
+
`slugPath` and `collectionSlugPath` accept absolute paths and collection-ID
|
|
551
|
+
anchors, with the same snapshot and scope rules as name paths. Pass decoded
|
|
552
|
+
segments, for example `coll_ID/getting-started`. The URL route should be decoded
|
|
553
|
+
once by your framework before passing it to the SDK.
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
import { toContentURL } from "@andesine/sdk";
|
|
557
|
+
|
|
558
|
+
// Prefer the API object: its slugPath also covers symbol-only ancestor names.
|
|
559
|
+
const url = toContentURL(page, { rootPath: "/Docs", baseURL: "/docs" });
|
|
560
|
+
// /docs/getting-started
|
|
561
|
+
const originalNames = toContentURL(page, { format: "name" });
|
|
562
|
+
// /Docs/Getting%20started
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
`toContentURL` defaults to slug URLs. A string input derives slugs from the path;
|
|
566
|
+
API objects use their returned `slugPath`. `format: "name"` preserves original
|
|
567
|
+
names. `rootPath` accepts a name or slug prefix in slug mode. Destination prefixes
|
|
568
|
+
and heading anchors are not slugified. `toContentSlug(name, id?)` exposes the
|
|
569
|
+
shared segment rule; symbol-only names require a public content ID. It is also
|
|
570
|
+
available from `@andesine/sdk/slug`, which loads only the slug helper.
|
|
571
|
+
|
|
572
|
+
Search indexes must be rebuilt after this upgrade to populate `slugPath` on
|
|
573
|
+
existing results and AI sources. No database schema migration is needed.
|
|
461
574
|
|
|
462
575
|
HTTP reads use query selectors on `GET /entries/get`, `GET /content/entries/get`,
|
|
463
576
|
`GET /content/tree`, and `GET /schemas/collection`. The published schema route
|
|
@@ -473,7 +586,7 @@ publication leaves the channel and its snapshot unchanged.
|
|
|
473
586
|
## Search and source links
|
|
474
587
|
|
|
475
588
|
Published search results include required `channel`, `snapshotID`, `versionID`,
|
|
476
|
-
and canonical entry `path` fields. `entryID` remains the stable identity.
|
|
589
|
+
and canonical entry `path` and `slugPath` fields. `entryID` remains the stable identity.
|
|
477
590
|
An optional `anchor` identifies a heading in that version; a result before any
|
|
478
591
|
heading has no anchor. Current results have their indexed working path. Search
|
|
479
592
|
index updates are asynchronous, so current paths can briefly lag draft changes.
|
|
@@ -488,9 +601,8 @@ for (const result of matches.results) {
|
|
|
488
601
|
const page = await client.atSnapshot(result.snapshotID).get({
|
|
489
602
|
entryID: result.entryID
|
|
490
603
|
});
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
// Map pathname to your docs site's route and render page with matching heading IDs.
|
|
604
|
+
const link = toContentURL(result, { rootPath: "/Docs", baseURL: "/docs" });
|
|
605
|
+
// Render page headings with matching IDs.
|
|
494
606
|
}
|
|
495
607
|
```
|
|
496
608
|
|
|
@@ -547,9 +659,9 @@ Both complete and streamed answers use the same inputs and source-selection rule
|
|
|
547
659
|
|
|
548
660
|
The limits are 1,000 characters per question, 10 history messages of up to 4,000
|
|
549
661
|
characters each, and 20 property filters. History is supplied per request; the SDK
|
|
550
|
-
does not store it. Trim history before sending a later question.
|
|
551
|
-
AI
|
|
552
|
-
|
|
662
|
+
does not store it. Trim history before sending a later question. Each answer uses 3
|
|
663
|
+
AI credits and has its own rate limit; see [Limits and usage](#limits-and-usage). A
|
|
664
|
+
complete response is counted when it succeeds.
|
|
553
665
|
A rate-limit error includes `Retry-After` and `data.retryAfterSeconds`. Provider
|
|
554
666
|
failures return `SERVICE_UNAVAILABLE` with hints. Answer POST requests are never
|
|
555
667
|
automatically retried, even when read retries are enabled.
|
|
@@ -590,6 +702,121 @@ on publication, with issue paths and available entry, version, and revision IDs.
|
|
|
590
702
|
Use `error.is(code)` to read the generated error data types. Schema definitions
|
|
591
703
|
remain readable when their associated document is invalid.
|
|
592
704
|
|
|
705
|
+
## Type-generation metadata
|
|
706
|
+
|
|
707
|
+
Read collection/schema metadata in bulk without fetching content bodies:
|
|
708
|
+
|
|
709
|
+
```ts
|
|
710
|
+
const published = await client.typeMetadata.getPublished({
|
|
711
|
+
collections: ["/Tutorials"],
|
|
712
|
+
channel: "published",
|
|
713
|
+
includeEntries: true
|
|
714
|
+
});
|
|
715
|
+
const current = await client.typeMetadata.getCurrent({
|
|
716
|
+
collections: ["/Tutorials"],
|
|
717
|
+
includeTree: true
|
|
718
|
+
});
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
Selectors accept IDs, decoded name paths, or `{ collectionSlugPath: "/docs" }`
|
|
722
|
+
objects and include descendant collections. An
|
|
723
|
+
empty list selects all accessible collections. Each response is one consistent
|
|
724
|
+
database snapshot; published metadata also returns its publication snapshot ID
|
|
725
|
+
for related reads. Published paths and schemas come from the assigned versions,
|
|
726
|
+
including mixed revisions and schema-free entries. A collection without recorded
|
|
727
|
+
schemas uses a general type without a warning. Current metadata uses active
|
|
728
|
+
effective schemas and rejects selected collections with an active schema migration.
|
|
729
|
+
|
|
730
|
+
`revisions` contains the referenced effective definitions, including inherited
|
|
731
|
+
fields. Each collection lists its `schemaRevisionIDs`: `null` means schema-free
|
|
732
|
+
content, while an empty array means there is no recorded schema evidence.
|
|
733
|
+
`includeEntries` adds entry identifiers, names, paths, and revision associations;
|
|
734
|
+
`includeTree` also includes entries and adds child IDs in display order. Current
|
|
735
|
+
entry/tree metadata requires `read:entries` in addition to `read:collections`.
|
|
736
|
+
Published metadata follows the existing `read:publishing` access rules.
|
|
737
|
+
|
|
738
|
+
The `fingerprint` changes with the returned type metadata. It excludes content
|
|
739
|
+
bodies, snapshot IDs, expiry, and entry/tree data that was not requested. These
|
|
740
|
+
endpoints provide metadata only; `andesine types generate` creates project declarations.
|
|
741
|
+
|
|
742
|
+
## Workspace content types
|
|
743
|
+
|
|
744
|
+
`createClient<Workspace>()` accepts a type-only workspace map. Generate it with
|
|
745
|
+
`andesine types generate`. A small map can also be defined directly:
|
|
746
|
+
|
|
747
|
+
```ts
|
|
748
|
+
import {
|
|
749
|
+
createClient,
|
|
750
|
+
toStructuredContent,
|
|
751
|
+
type EntryFragment,
|
|
752
|
+
type WorkspaceCollection,
|
|
753
|
+
type WorkspaceTypeMap
|
|
754
|
+
} from "@andesine/sdk";
|
|
755
|
+
|
|
756
|
+
interface Tutorials extends WorkspaceCollection {
|
|
757
|
+
id: "coll_tutorials";
|
|
758
|
+
path: "/Tutorials";
|
|
759
|
+
slugPath: "/tutorials";
|
|
760
|
+
schemaRevisionIDs: readonly ["schr_tutorial"];
|
|
761
|
+
descendants: readonly [];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
interface Workspace extends WorkspaceTypeMap {
|
|
765
|
+
source: { kind: "published"; channel: "published" };
|
|
766
|
+
collections: { "coll_tutorials": Tutorials; "/Tutorials": Tutorials; "/tutorials": Tutorials };
|
|
767
|
+
schemas: {
|
|
768
|
+
schr_tutorial: {
|
|
769
|
+
hash: "RECORDED_SCHEMA_HASH";
|
|
770
|
+
properties: {
|
|
771
|
+
title: { name: "Title"; type: "text"; value: string };
|
|
772
|
+
duration?: { name: "Duration"; type: "number"; value: number | null };
|
|
773
|
+
};
|
|
774
|
+
fragments: { body: EntryFragment };
|
|
775
|
+
};
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const client = createClient<Workspace>();
|
|
780
|
+
|
|
781
|
+
for await (const entry of client.content.paginateEntries({
|
|
782
|
+
collectionPath: "/Tutorials",
|
|
783
|
+
channel: "published",
|
|
784
|
+
includeContent: true
|
|
785
|
+
})) {
|
|
786
|
+
const tutorial = toStructuredContent(entry);
|
|
787
|
+
const title: string = tutorial.properties.title;
|
|
788
|
+
const duration: number | null | undefined = tutorial.properties.duration;
|
|
789
|
+
}
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
Replace the example IDs, hash, and fields with the recorded metadata. Collections
|
|
793
|
+
can have several revision IDs; results then preserve each revision's fields as a
|
|
794
|
+
union. `null` represents schema-free content. An empty revision tuple uses general
|
|
795
|
+
content types. `descendants` contains all descendant collection keys; recursive
|
|
796
|
+
lists include their shapes. If the hierarchy is incomplete, recursive results
|
|
797
|
+
also retain the general content type.
|
|
798
|
+
|
|
799
|
+
Exact entry reads narrow only when the map has an `entries` binding for the given
|
|
800
|
+
ID, path, or slug path. Each binding supplies `collection` and `schemaRevisionID`. Optional
|
|
801
|
+
`tree` bindings supply published tree shapes by collection selector. Unknown keys
|
|
802
|
+
and dynamic strings keep general SDK types. Current maps apply to `entries.get`;
|
|
803
|
+
published maps apply to content delivery. Summary lists do not gain content fields.
|
|
804
|
+
Snapshots, full responses, pagination, and `toStructuredContent` preserve the map.
|
|
805
|
+
|
|
806
|
+
`SchemaContent<Workspace, "schr_tutorial">` exposes one revision's content fields.
|
|
807
|
+
`OperationOutput<"content.get", Workspace, { path: "/Tutorials/First" }>` exposes
|
|
808
|
+
a full result when that entry path is bound. For mixed revisions, TypeScript does
|
|
809
|
+
not narrow the parent entry after a nested `entry.schema.revisionID` check. Use a
|
|
810
|
+
type predicate with `Extract<Result, { schema: { revisionID: "schr_tutorial" } }>`
|
|
811
|
+
to narrow the entry. Collection lists can also narrow on their top-level
|
|
812
|
+
`collectionID` when the collections have distinct IDs.
|
|
813
|
+
|
|
814
|
+
The map makes no requests and changes no request options. Supply the workspace,
|
|
815
|
+
channel, and snapshot through the usual runtime options. The types assume those
|
|
816
|
+
options and the server content match the map; they do not validate responses or
|
|
817
|
+
detect stale generated types. Different clients can use different maps without
|
|
818
|
+
module augmentation. Plain `createClient()` keeps the general SDK types.
|
|
819
|
+
|
|
593
820
|
## Operation documentation and error hints
|
|
594
821
|
|
|
595
822
|
All public methods include generated summaries, descriptions, API key permissions,
|
|
@@ -670,11 +897,10 @@ Missing completion or an interrupted body uses `INCOMPLETE_STREAM`. These are
|
|
|
670
897
|
local protocol errors, not API errors with an invented HTTP status. Abort and
|
|
671
898
|
timeout reasons are preserved.
|
|
672
899
|
|
|
673
|
-
A stream
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
additional usage records.
|
|
900
|
+
A stream is counted when generation starts, including generation that later fails
|
|
901
|
+
or is cancelled. Source preparation alone is not charged. The rate limit, quota, and
|
|
902
|
+
spending limit checks run before the stream opens. Usage headers show the allowance
|
|
903
|
+
when the stream opens; chunks do not update headers or create more usage records.
|
|
678
904
|
|
|
679
905
|
### Forward a stream from your server
|
|
680
906
|
|
|
@@ -726,3 +952,11 @@ JSON; `event: error` carries the error envelope. Completion is an application
|
|
|
726
952
|
`completed` event. Comments are ignored, and a transport `done` event cannot
|
|
727
953
|
replace application completion. Event IDs and retry fields never trigger
|
|
728
954
|
reconnection.
|
|
955
|
+
|
|
956
|
+
## Webhooks
|
|
957
|
+
|
|
958
|
+
Manage endpoints and delivery history through `client.webhooks`. Verify incoming
|
|
959
|
+
requests in server code with `verifyWebhook` or `verifyWebhookRequest` from
|
|
960
|
+
`@andesine/sdk/webhooks`. Both helpers return a validated, typed event after
|
|
961
|
+
authenticating the unchanged body and checking the five-minute timestamp window.
|
|
962
|
+
See [webhook setup, receivers, rotation, and replay](WEBHOOKS.md).
|