@capacms/sdk 1.0.0-next.4 → 1.0.0-next.7
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 +345 -0
- package/README.md +1069 -186
- package/bin/capa-codegen.js +192 -5
- package/bin/capa.js +208 -0
- package/bin/graphql-project.js +142 -0
- package/bin/project-env.js +58 -0
- package/dist/client.d.ts +5 -0
- package/dist/client.js +17 -0
- package/dist/codegen.d.ts +55 -0
- package/dist/codegen.js +320 -39
- package/dist/config.d.ts +5 -36
- package/dist/config.js +47 -1
- package/dist/graphql-codegen.d.ts +117 -0
- package/dist/graphql-codegen.js +705 -0
- package/dist/http.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/next/attrs.d.ts +51 -12
- package/dist/next/attrs.js +74 -20
- package/dist/next/client.d.ts +112 -38
- package/dist/next/client.js +131 -83
- package/dist/next/entry-fields.d.ts +162 -0
- package/dist/next/entry-fields.js +2 -0
- package/dist/next/errors.d.ts +136 -0
- package/dist/next/errors.js +214 -0
- package/dist/next/field-names.d.ts +37 -0
- package/dist/next/field-names.js +145 -0
- package/dist/next/graphql/build.d.ts +27 -0
- package/dist/next/graphql/build.js +98 -0
- package/dist/next/graphql/documents.d.ts +67 -0
- package/dist/next/graphql/documents.js +35 -0
- package/dist/next/graphql/edit-mode.d.ts +16 -0
- package/dist/next/graphql/edit-mode.js +93 -0
- package/dist/next/graphql/filter-values.d.ts +34 -0
- package/dist/next/graphql/filter-values.js +96 -0
- package/dist/next/graphql/introspection.d.ts +89 -0
- package/dist/next/graphql/introspection.js +102 -0
- package/dist/next/graphql/plan.d.ts +115 -0
- package/dist/next/graphql/plan.js +531 -0
- package/dist/next/graphql/request.d.ts +228 -0
- package/dist/next/graphql/request.js +283 -0
- package/dist/next/graphql/rest.d.ts +66 -0
- package/dist/next/graphql/rest.js +502 -0
- package/dist/next/graphql/selection.d.ts +55 -0
- package/dist/next/graphql/selection.js +212 -0
- package/dist/next/graphql/sha256.d.ts +13 -0
- package/dist/next/graphql/sha256.js +86 -0
- package/dist/next/graphql/summary.d.ts +83 -0
- package/dist/next/graphql/summary.js +151 -0
- package/dist/next/graphql/tree-layout.d.ts +36 -0
- package/dist/next/graphql/tree-layout.js +20 -0
- package/dist/next/graphql/tree.d.ts +171 -0
- package/dist/next/graphql/tree.js +249 -0
- package/dist/next/graphql/typed.d.ts +261 -0
- package/dist/next/graphql/typed.js +146 -0
- package/dist/next/index.d.ts +28 -5
- package/dist/next/index.js +25 -1
- package/dist/next/inflate.d.ts +25 -7
- package/dist/next/inflate.js +46 -32
- package/dist/next/key-family.d.ts +34 -0
- package/dist/next/key-family.js +74 -0
- package/dist/next/select-types.d.ts +44 -8
- package/dist/next/system-keys.d.ts +27 -0
- package/dist/next/system-keys.js +42 -0
- package/dist/nextjs/index.d.ts +174 -12
- package/dist/nextjs/index.js +270 -23
- package/dist/nextjs/overlay.d.ts +5 -0
- package/dist/nextjs/overlay.js +35 -0
- package/package.json +31 -13
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# @capacms/sdk changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- 1.0.0-next.7. Browsers: the `/api/` and legacy clients called the platform `fetch` as a
|
|
6
|
+
method of their config, which a browser refuses ("Failed to execute 'fetch'
|
|
7
|
+
on 'Window': Illegal invocation"), so every read from a browser failed unless
|
|
8
|
+
`fetch` was passed in. The default fetch is now called through `globalThis`
|
|
9
|
+
on each request, which also picks up a fetch a framework patches in later.
|
|
10
|
+
- `next` is no longer a peer dependency. No range matches every Next canary,
|
|
11
|
+
so a site on `next@16.3.0-canary.39` could not `npm install` the SDK without
|
|
12
|
+
`--legacy-peer-deps`. `@capacms/sdk/nextjs/overlay` still imports `next`,
|
|
13
|
+
which only a Next site loads.
|
|
14
|
+
- Docs: the edit mark is dropped wherever an entry is serialized to the
|
|
15
|
+
browser (Pages Router props, SvelteKit and Remix loaders, Nuxt payload);
|
|
16
|
+
pass the edit flag to `capaAttrs` there. Found testing preview on nine stacks.
|
|
17
|
+
- Next.js: a GraphQL read that gives neither `tags` nor `revalidate`, through
|
|
18
|
+
`getCapaClient().graphql()`, its builder or `graphql()`, is no longer kept
|
|
19
|
+
in Next's data cache. It is sent as `entries.list` and `entries.get` send
|
|
20
|
+
theirs, with no `cache` and no `next`, so a publish shows on the next render
|
|
21
|
+
whether the page reads by REST or by GraphQL. It used to be kept under
|
|
22
|
+
`capa:graphql` until a webhook revalidated it, so a site with no webhook
|
|
23
|
+
route kept serving the old answer by GraphQL while REST showed the new one.
|
|
24
|
+
A read that gives `tags` or a `revalidate` is kept as before. To keep a read
|
|
25
|
+
with no tags as it was kept, pass `revalidate: false`, which keeps it under
|
|
26
|
+
`capa:graphql` until the next publish. `tags: []` now counts as no tags.
|
|
27
|
+
- 1.0.0-next.6. GraphQL, on `@capacms/sdk/next` and `@capacms/sdk/nextjs`,
|
|
28
|
+
and two commands, `capa-codegen --graphql` and `capa persist`. Additive:
|
|
29
|
+
every call that existed behaves as before. `graphql` is an optional peer
|
|
30
|
+
dependency that only the two commands load. The package's types now need
|
|
31
|
+
TypeScript 5.0 or later, with `strict` on or off.
|
|
32
|
+
|
|
33
|
+
Calls and errors. `client.graphql(document, variables?, options?)` runs a
|
|
34
|
+
query against `/api/graphql` and resolves with
|
|
35
|
+
`{ data, errors, extensions, cacheTags }` once the API has run it, even
|
|
36
|
+
when `errors` is not empty: a root field that failed is `null` and the
|
|
37
|
+
others keep their data. A request the API refuses as a whole, `errors` and
|
|
38
|
+
no `data`, throws `CapaError` whatever its status: a 4xx, or the 200 that
|
|
39
|
+
GraphQL over HTTP sends on `application/json`, thrown with `status` 400.
|
|
40
|
+
401, 402, 403, 404, 405 and 429 keep their own. `CapaError` carries every
|
|
41
|
+
error of the refusal in `graphqlErrors`. Each error is a
|
|
42
|
+
`CapaGraphQLError`, a plain object: `message`, `locations`, `path` and
|
|
43
|
+
`extensions` as the spec writes them, with `code`, `hint`, `docs`, `param`
|
|
44
|
+
and `type` lifted out, so `Response.json(result)` and a client component's
|
|
45
|
+
props keep every field. `isCapaGraphQLError` checks one by its shape.
|
|
46
|
+
Where GraphQL is switched off (`CAPA_API_GRAPHQL=off`) the call throws
|
|
47
|
+
"This Capa deployment does not serve GraphQL." with a hint to read over
|
|
48
|
+
REST meanwhile. `extensions.cost` (`requestedQueryCost`,
|
|
49
|
+
`actualQueryCost`, and `budget`, whose `counted` is what the 5,000-entry
|
|
50
|
+
limit checks) and `extensions.deprecations` (`{ coordinate, reason }` for
|
|
51
|
+
each deprecated member a document used) are typed.
|
|
52
|
+
|
|
53
|
+
Sending. A read is a GET whenever its URL fits the API's 8,192-byte limit,
|
|
54
|
+
so a production key's read is cached by the CDN and the API with no option
|
|
55
|
+
set, and a POST when it does not; no document is refused for its length.
|
|
56
|
+
`method: "POST"` always sends a POST. A host that serves GraphQL by POST
|
|
57
|
+
only (the admin host) answers a GET as a path it does not serve; the read
|
|
58
|
+
is repeated as a POST, and that host is read by POST for five minutes. A
|
|
59
|
+
429 (over the API's read limits: 4 running per project, 3 of them per
|
|
60
|
+
client, and 64 waiting per client or 256 per key, with `/api/entries`
|
|
61
|
+
reads counted in the same limits) is sent again after its `Retry-After`
|
|
62
|
+
plus up to 250 ms, up to 3 times; `retries: 0` throws it, and a thrown 429
|
|
63
|
+
carries `retryAfter` in seconds, on REST calls too. `createClient` takes the legacy key a site holds for
|
|
64
|
+
every read, `pk_`, `sk_` or unprefixed as older tenants were minted, and
|
|
65
|
+
warns once per process without printing any of it; `preview()` and draft
|
|
66
|
+
reads (`draftClient`, `CAPA_DRAFT_KEY`) take a `cap_` key only.
|
|
67
|
+
|
|
68
|
+
Persisted queries. `persisted: true` sends the document's sha256 as a
|
|
69
|
+
cacheable GET (a POST when the variables are too long for a URL), and on
|
|
70
|
+
`PersistedQueryNotFound` one POST with the document. The API stores a
|
|
71
|
+
document only for a development key; a hash a host declined is
|
|
72
|
+
remembered for five minutes and sent by POST meanwhile. `capa persist`
|
|
73
|
+
registers a project's documents at build time, with the development key
|
|
74
|
+
in `CAPA_DRAFT_KEY`, on `CAPA_API_URL` (`CAPA_ADMIN_URL` for a self-hosted
|
|
75
|
+
stack whose read host stores nothing), and refuses a production key
|
|
76
|
+
before it sends anything. Every document is pinned (`Capa-Persist: pin`),
|
|
77
|
+
so documents registered in the Explorer or a preview never evict it, and
|
|
78
|
+
one stored without its pin fails the run. A refusal is reported with its
|
|
79
|
+
code. `--release` and `--env` name the build its pins belong to
|
|
80
|
+
(`Capa-Persist: pin; release=<id>; env=<env>`), read from Vercel's and
|
|
81
|
+
Netlify's build variables when not given, so the API keeps the latest
|
|
82
|
+
production releases' documents before a preview's.
|
|
83
|
+
|
|
84
|
+
Typed documents. `capa-codegen --graphql` checks the project's `.graphql`
|
|
85
|
+
files and its `#graphql`, `/* capa */` and gql`` literals against the
|
|
86
|
+
key's schema, and writes one module: the schema's types, `CapaQuery`, a
|
|
87
|
+
`TypedDocument` per operation with `<Name>Models`, the models it reads,
|
|
88
|
+
beside it, a `<Name>Fragment` per fragment and `capaTreeLayout`.
|
|
89
|
+
`tagsFor({ namespace: <Name>Models })` tags a Next.js read with every model
|
|
90
|
+
its query reads, relations and filters through them included, so no model
|
|
91
|
+
is left out by hand, and with `capa:media`, which `revalidateFromWebhook`
|
|
92
|
+
revalidates when a file in the media library is edited. `client.graphql(doc, vars)` then infers data and
|
|
93
|
+
variables with no cast, a literal is typed by its own text, and a
|
|
94
|
+
document's required variables are required in the call. A literal codegen
|
|
95
|
+
has not read yet does not compile (`RunCapaCodegen`). A fragment in a
|
|
96
|
+
literal of its own, spread with `${FRAGMENT}` into a query kept
|
|
97
|
+
`as const`, works as in Hydrogen. A field, argument or value a later
|
|
98
|
+
`Capa-Version` phases out is `@deprecated`, and each use is printed with
|
|
99
|
+
its file, line and reason. `--watch`, `--check`, `--save-schema` and
|
|
100
|
+
`--schema` are supported. Both commands read `CAPA_API_URL` and `CAPA_KEY`
|
|
101
|
+
(`CAPA_BASE_URL` and `CAPA_API_KEY` still work) from the shell or the
|
|
102
|
+
project's `.env` files, as `next dev` does.
|
|
103
|
+
|
|
104
|
+
REST types. `capa-codegen` without `--graphql` takes a `cap_` key: it
|
|
105
|
+
writes the model interfaces the `/v2` schema gives a legacy key from the
|
|
106
|
+
key's GraphQL schema, keyed by namespace, with no tenant id, and from a
|
|
107
|
+
saved schema with `--schema`. Every field is optional there, an enum is a
|
|
108
|
+
`string` and a field GraphQL leaves out is `unknown`, since GraphQL does
|
|
109
|
+
not say more; no `CAPA_SCHEMA_CHECKSUM` is written. Whichever key reads
|
|
110
|
+
it, the module now parses for any namespace: a field that is not an
|
|
111
|
+
identifier is quoted (`"am/pm_indicator"?: string;`), a model whose
|
|
112
|
+
PascalCase name is not one is named as GraphQL names it (`2024_events` is
|
|
113
|
+
`_2024Events`, its references and `Select` and `Attrs` aliases too), and an
|
|
114
|
+
enum's values are escaped. A read's `fields` is typed as the API returns
|
|
115
|
+
it: `entries.list<Articles, typeof select>` types exactly the fields the
|
|
116
|
+
select names, each always there and `null` when it was never filled, an
|
|
117
|
+
expanded relation as the entry (with `fields`) or
|
|
118
|
+
`{ id, model, missing: true }`, one it does not expand as `{ id, model }`,
|
|
119
|
+
a relation list as `{ items, pageInfo }` and media as
|
|
120
|
+
`{ id, url, alt, type, width, height }` (`EntryFields`). A select the
|
|
121
|
+
compiler cannot read, a string or one typed `Select<T>`, types every field
|
|
122
|
+
and each relation as any of the three. A flat read's relations are
|
|
123
|
+
references, `included` holds partial entries, and `inflate` returns the
|
|
124
|
+
tree read's type. BREAKING for code that compiled against the stored
|
|
125
|
+
shape (`fields.author.name`, `fields.coauthors[0]`), which read
|
|
126
|
+
`undefined` or threw at run time. A relation may be named alone in a
|
|
127
|
+
typed select, as a reference.
|
|
128
|
+
|
|
129
|
+
The typed builder. `client.graphql.query(selection)` builds the document
|
|
130
|
+
from an object and, with `createClient<CapaQuery>()`, types the result from
|
|
131
|
+
exactly what was selected. A misspelled field, argument, filter field or
|
|
132
|
+
operator, an argument of the wrong type, a sort value outside the enum
|
|
133
|
+
and a missing required argument (`article` without `args: { id }`) do not
|
|
134
|
+
compile, and the compiler's error names the key and where it was written
|
|
135
|
+
(`SelectionError<"titel is not a field of articles.nodes">`).
|
|
136
|
+
`NodeOf<CapaQuery, typeof selection, "articles">` is one entry of a read,
|
|
137
|
+
for a component's props, and `QueryResult` the whole of its `data`. An alias reads a field again in the same request:
|
|
138
|
+
`{ latest: { __aliasFor: "articles", args, nodes } }` is sent as
|
|
139
|
+
`latest: articles(...)`, and typed and checked as `articles`. A `Date` in
|
|
140
|
+
`args` is sent as its ISO text. `selectionToDocument` returns the text a
|
|
141
|
+
selection sends. It takes no `persisted`, and throws a `TypeError` for it
|
|
142
|
+
before any request: its document is printed when it runs, so `capa persist`
|
|
143
|
+
never stored it, and it is already a cacheable GET.
|
|
144
|
+
|
|
145
|
+
Paging, tags and descriptions. The builders page back as the API does:
|
|
146
|
+
REST's `before` with a `limit` is sent as `last` with `before`, and
|
|
147
|
+
`before=end` as `last` alone, the end of the list. A model's filter takes
|
|
148
|
+
`_tags`, as REST's `where` takes `$tags`, with the operators the key's
|
|
149
|
+
schema declares for it. `graphqlSchema()`, the builders and codegen read a
|
|
150
|
+
field's `Capa field ...` tag from the last line of its description, after
|
|
151
|
+
the field's label, which is where the API writes it.
|
|
152
|
+
|
|
153
|
+
REST's shape. `toTree(data, selection, layout)` turns a builder result into
|
|
154
|
+
REST's `shape=tree` data for the same read, typed from the selection:
|
|
155
|
+
system keys beside `fields`, each field under its namespace, media values
|
|
156
|
+
in REST's public shape and order (`id`, `url`, `alt`, `type`, `width`,
|
|
157
|
+
`height`), and each entry's `model` from the layout. A relation list
|
|
158
|
+
without `pageInfo` selected is `{ items }`, and a missing item of one is
|
|
159
|
+
left out, where REST keeps a `{ id, model, missing: true }` slot. The layout
|
|
160
|
+
is the `capaTreeLayout` constant codegen writes, so a server reads no schema
|
|
161
|
+
for it, or a schema read with `client.graphqlSchema()`. A root alias
|
|
162
|
+
converts as the field it names; an alias below a root is refused, since
|
|
163
|
+
REST reads each field once. `selectToSelection` writes a REST read as a
|
|
164
|
+
builder selection, and `graphqlToSelect` takes a selection back to REST
|
|
165
|
+
as it takes a tool spec.
|
|
166
|
+
|
|
167
|
+
The tool spec. `buildGraphQLQuery`, `graphqlToSelect` and `selectToGraphQL`
|
|
168
|
+
move between the spec the Explorer and `@capa/mcp` share, GraphQL text and
|
|
169
|
+
the equal REST request, written exactly as the API writes it in
|
|
170
|
+
`extensions.capa.rest`: the filter as `where` JSON, and a system key a
|
|
171
|
+
field shadows as `$tags`, `$createdAt` or `author.$id`. They nest at most 4
|
|
172
|
+
relations below the root entry, which is the API's 5 levels of entries,
|
|
173
|
+
and send each filter value as the type its filter input declares, so
|
|
174
|
+
`has: "true"` on a list of true/false values goes as `true`. They check a
|
|
175
|
+
filter's names through `and`, `or`, `not` and one hop, refuse a system
|
|
176
|
+
field GraphQL does not filter (`_version`) and a hop through a relation the
|
|
177
|
+
key cannot read without naming the hidden model, and refuse a key a spec
|
|
178
|
+
does not take (`frist`) with the keys it does. `selectToGraphQL` selects
|
|
179
|
+
what REST returns: all six media fields, and for `*` or no select the
|
|
180
|
+
system keys, every field and each relation list as a connection of ids.
|
|
181
|
+
`inflate` and `Select<T>` read `$tags`, `$createdAt` and the other `$`
|
|
182
|
+
names as system keys (`SystemKey`). The schema summary lists the models
|
|
183
|
+
GraphQL leaves out in `restOnly`, and the builder refuses one by naming
|
|
184
|
+
its REST read, never as an unknown model with another model suggested.
|
|
185
|
+
A read of one entry pages a relation list from a cursor: `after` on the
|
|
186
|
+
relation's spec, `after:` in a select, `args.after` in a selection. A list
|
|
187
|
+
read refuses it, as the API does. `sort` takes one value or a list, at the
|
|
188
|
+
root too. A spec written as REST writes a read (`author.name`,
|
|
189
|
+
`author(name)`, `*`, a sort of `-publishedAt`) throws with what to write
|
|
190
|
+
instead.
|
|
191
|
+
|
|
192
|
+
Next.js. `graphql()` on `@capacms/sdk/nextjs` reads `CAPA_API_URL`,
|
|
193
|
+
`CAPA_KEY` and `CAPA_API_VERSION` (a setting in `config` wins), works out
|
|
194
|
+
draft and edit mode from `{ draftMode, headers }` as `getCapaClient` does,
|
|
195
|
+
and keeps a published read that answered with no `errors` in Next's data
|
|
196
|
+
cache, through `unstable_cache`, under its `tags`: until one of them is
|
|
197
|
+
revalidated, or for `revalidate` seconds. A read with no `tags` is tagged
|
|
198
|
+
`capa:graphql` (`GRAPHQL_TAG`), which `revalidateFromWebhook` revalidates
|
|
199
|
+
on every content and media event; `tagsFor({ namespace })` tags a read by
|
|
200
|
+
the models it reads. Drafts are read uncached, by GET. It is not
|
|
201
|
+
persisted by default. `draftClient`, `getCapaClient` and
|
|
202
|
+
`getPublishedClient` take `CapaQuery` like `createClient`, and
|
|
203
|
+
`getCapaClient` keeps its GraphQL reads, a document or the typed builder,
|
|
204
|
+
in Next's data cache the same way, under the `tags` and `revalidate` each
|
|
205
|
+
call gives.
|
|
206
|
+
|
|
207
|
+
The package root. `createClient` from `@capacms/sdk`, the legacy `/v2/api`
|
|
208
|
+
client, refuses a `cap_` key with a `TypeError` that names
|
|
209
|
+
`@capacms/sdk/next`, before it asks for a tenant id or sends anything,
|
|
210
|
+
where every read failed as a 401 "Invalid API key". Its `CapaError`
|
|
211
|
+
message joins the body with a colon. The README opens with which import is
|
|
212
|
+
which and links the API reference, and `homepage` is
|
|
213
|
+
https://docs.capacms.com/api.
|
|
214
|
+
|
|
215
|
+
Edit mode. A GraphQL read in edit mode is marked like a REST read: each
|
|
216
|
+
object that selected `id` and `model` is an entry, and
|
|
217
|
+
`capaAttrs(node, field)` and `fieldAttrs(node)` tag a field GraphQL renamed
|
|
218
|
+
by its namespace. To know which fields those are, the client reads the
|
|
219
|
+
key's type and field names once a minute, beside the page's read rather
|
|
220
|
+
than after it; a document that never says `model` reads none. `toTree`
|
|
221
|
+
keeps the mark, and `markGraphQLEntries` is exported. With next.5's
|
|
222
|
+
`FieldAttrs<T>`: `fieldAttrs` also takes a GraphQL node and, for a REST
|
|
223
|
+
entry typed with `Model`, still returns exactly `FieldAttrs<Model>`, so the
|
|
224
|
+
`<Model>Attrs` aliases codegen writes keep working. `TaggableField<E>` is
|
|
225
|
+
exported beside it.
|
|
226
|
+
|
|
227
|
+
- 1.0.0-next.5. `<CapaOverlay adminOrigins={[...]} />` from the new entry
|
|
228
|
+
point `@capacms/sdk/nextjs/overlay`: the live preview overlay as one Next.js
|
|
229
|
+
client component, refreshing with `router.refresh()` on save (M6). `react`
|
|
230
|
+
and `next` are optional peer dependencies, needed only for that entry. The
|
|
231
|
+
`FieldAttrs<T>` type is exported from `@capacms/sdk/next`, and `capa-codegen`
|
|
232
|
+
writes a `<Model>Attrs` alias beside each `<Model>Select`, so
|
|
233
|
+
`const a: ArticleAttrs = fieldAttrs(entry)` catches a wrong field name at
|
|
234
|
+
compile time (M5).
|
|
235
|
+
- 1.0.0-next.4. Edit mode. BREAKING for sites that call `capaAttrs(entry,
|
|
236
|
+
field)` with no third argument: it now tags only entries read in edit mode, so
|
|
237
|
+
a published page ships no `data-capa-` attributes. Create the client with
|
|
238
|
+
`editMode: true` (work it out with `editMode({ draftMode, headers })` from
|
|
239
|
+
`@capacms/sdk/nextjs`) and every entry it reads, related entries included, is
|
|
240
|
+
marked. Sites that pass a flag keep working unchanged. New in
|
|
241
|
+
`@capacms/sdk/nextjs`: `editMode`, `resolveEditRequest` for middleware (checks
|
|
242
|
+
a `capa-edit` token with Capa, strips a forged `x-capa-edit`, returns the
|
|
243
|
+
`private, no-store` Cache-Control to set), and the constants `EDIT_PARAM`,
|
|
244
|
+
`EDIT_HEADER`, `DRAFT_COOKIE`, `EDIT_CACHE_CONTROL`. New on the client: a
|
|
245
|
+
`path` option (config and per call) sent as `Capa-Path` beside `Capa-Page`, so
|
|
246
|
+
Capa can list the concrete URLs an entry appears on. `markEditEntries`,
|
|
247
|
+
`isEditEntry` and `CAPA_EDIT` are exported from `@capacms/sdk/next`.
|
|
248
|
+
Five-minute integration (M6) in `@capacms/sdk/nextjs`: `getCapaClient`
|
|
249
|
+
(keys and edit mode from env), `getPublishedClient`, `createPreviewRoute`,
|
|
250
|
+
`exitPreviewRoute` and `capaMiddleware` (preview links, the Published view,
|
|
251
|
+
edit mode and `no-store` in one line). Typed `fieldAttrs(entry).title` on
|
|
252
|
+
`@capacms/sdk/next` (M5): a wrong field name is a compile error.
|
|
253
|
+
Flat responses: `entries.list` and `entries.get` take `shape: "flat"`, which
|
|
254
|
+
sends `?shape=flat` and returns every relation as a `{ id, model }`
|
|
255
|
+
reference with each expanded entry once in `included`, typed by the select.
|
|
256
|
+
The result carries the select it sent. `inflate(result)` turns it back into
|
|
257
|
+
the tree result, deep-equal to a `shape=tree` read of the same request; it
|
|
258
|
+
returns copies and stops where the select stops, so cycles end. New types:
|
|
259
|
+
`FlatPage`, `FlatSingle`, `FlatListOptions`, `FlatGetOptions`, `Included`,
|
|
260
|
+
`ExpandedTargets`, `ResponseShape`, `FlatResponse`. Additive: a read without
|
|
261
|
+
`shape` sends the same URL and returns the same result as before.
|
|
262
|
+
- 1.0.0-next.3. Reads made from a layout are no longer charged to `/`.
|
|
263
|
+
`routeOf` returned the route a file sits at, so `app/layout.tsx` came out as
|
|
264
|
+
`/` and every Site singleton or nav read in a root layout was recorded as a
|
|
265
|
+
read of the home page, on every page of the site. `routeOf` now returns
|
|
266
|
+
`"(layout)"` (exported as `LAYOUT_PAGE` from `@capacms/sdk/next` and
|
|
267
|
+
`@capacms/sdk/nextjs`) for an app-router `layout.*` or `template.*`, and a
|
|
268
|
+
read whose page is `"(layout)"` sends no `Capa-Page`, even when the client was
|
|
269
|
+
created with a `page`. The return type is still `string`, so layout code that
|
|
270
|
+
already passes `routeOf(import.meta.url)` needs no change: upgrading fixes it.
|
|
271
|
+
No API change: the API already records nothing for a read without the
|
|
272
|
+
header. In the pages router, `pages/layout.tsx` is now the page `/layout`
|
|
273
|
+
rather than `/`.
|
|
274
|
+
- 1.0.0-next.2. The overlay reports `visible { entryId, field }`, the tagged
|
|
275
|
+
element at the centre of the viewport, while the page scrolls: at most every
|
|
276
|
+
150ms and only when it changes (the topmost visible element at the very top
|
|
277
|
+
of a page, the bottommost at the very bottom). The Capa editor's "Follow the
|
|
278
|
+
page" scrolls the form to match. Additive and still protocol `v: 1`, so an older admin
|
|
279
|
+
ignores it and an older overlay simply never sends it. `pickCentred` and
|
|
280
|
+
`scrollEdge`, the pure choice behind it, and `visibleMessage` are exported
|
|
281
|
+
for tests.
|
|
282
|
+
- 1.0.0-next.1. Live preview. `capaAttrs(entry, field, enabled)` on
|
|
283
|
+
`@capacms/sdk/next` tags an element with the entry and field it renders,
|
|
284
|
+
typed so `field` is one of the entry's data keys. The new entry point
|
|
285
|
+
`@capacms/sdk/overlay` exports `startOverlay({ adminOrigins, onRefresh })`,
|
|
286
|
+
which, inside the Capa editor's preview frame, outlines the field being
|
|
287
|
+
edited, reports clicks on tagged elements back to the editor and re-renders
|
|
288
|
+
the draft after a save. It does nothing outside a frame and has no
|
|
289
|
+
dependencies. `acceptMessage` is exported for tests. See "Live preview" in
|
|
290
|
+
the README.
|
|
291
|
+
- `routeOf(import.meta.url)` now decodes the file URL. A real `import.meta.url`
|
|
292
|
+
percent-encodes brackets, so a dynamic route such as `app/blog/[slug]/page.tsx`
|
|
293
|
+
came out as `/blog/%5Bslug%5D` and every read with that `page` threw a
|
|
294
|
+
`TypeError`.
|
|
295
|
+
- The package is published as `@capacms/sdk`. The `capa` scope on npm was
|
|
296
|
+
already taken, so the org is `capacms`; entry points are `@capacms/sdk`
|
|
297
|
+
(legacy `/v2` client), `@capacms/sdk/next` and `@capacms/sdk/nextjs`.
|
|
298
|
+
Nothing else about the package changed. Earlier notes below that named
|
|
299
|
+
`@capa/sdk` were written before the first publish and mean this package.
|
|
300
|
+
- Added `page` to `CapaNextConfig` and to every call's options, sending the
|
|
301
|
+
`Capa-Page` header so Capa can report which of a site's pages read which
|
|
302
|
+
entries. Telemetry only: it does not change a response, a cache key or an
|
|
303
|
+
`ETag`. A malformed value throws a `TypeError`, because the API ignores a
|
|
304
|
+
header it cannot store and a typo should surface where it is written.
|
|
305
|
+
- Added `client.pages.list()` and `client.pages.get(page)` for the page list and
|
|
306
|
+
one page's detail. `list({ entry })` narrows to the pages that read one entry
|
|
307
|
+
and adds `entryReads` to each row; `get` returns `null` for an unknown page.
|
|
308
|
+
- Added `client.preview(token)`, which verifies a preview token minted by the
|
|
309
|
+
Capa admin and returns the claim, or `null` when the token is invalid or
|
|
310
|
+
expired. Every other failure throws.
|
|
311
|
+
- Added `schemaChecksum` to `CapaNextConfig`, sending the `Capa-Schema` header on
|
|
312
|
+
every call so Capa can tell a site built against the current models from one
|
|
313
|
+
built against an older set. Telemetry only, like `page`: it changes no
|
|
314
|
+
response, cache key or `ETag`. A malformed value throws a `TypeError`, because
|
|
315
|
+
a stamp the API drops in silence looks exactly like a site that is up to date.
|
|
316
|
+
- `capa-codegen` now writes `export const CAPA_SCHEMA_CHECKSUM` beside the
|
|
317
|
+
checksum comment it already wrote, so the value can be imported and handed to
|
|
318
|
+
`createClient`. That constant is the only new byte in the generated file.
|
|
319
|
+
- `client.pages.get(page)` now carries `insights`, the suggestions Capa draws
|
|
320
|
+
from that page's own reads (`overfetch`, `fanout`, `cache`, `drift`), each
|
|
321
|
+
with the numbers behind it and a copyable rewrite where there is one, and
|
|
322
|
+
every `queries[]` row carries `selection`, the parsed Selection IR of its
|
|
323
|
+
`select`, or `selectionError` when it no longer parses.
|
|
324
|
+
- Every `queries[]` row on `client.pages.get(page)` also carries `url`, the
|
|
325
|
+
request that group most often made, so a caller can print the real call with
|
|
326
|
+
its filters, sort and limit instead of reconstructing one from `select`. It is
|
|
327
|
+
`null` once the group has been folded into the daily rollup, which keeps
|
|
328
|
+
counts rather than requests. The detail itself gains `lastReadAt`.
|
|
329
|
+
- `client.pages.list()` now carries `meta.insights`, the tenant-wide `unused`
|
|
330
|
+
rows: entries no page has read in 30 days and nobody has edited in 90.
|
|
331
|
+
- Added `routeOf(file)`, `preview(token, client)` and `pagesFor(client)` to
|
|
332
|
+
`@capacms/sdk/nextjs`. `routeOf` turns a Next route file into a page string,
|
|
333
|
+
dropping route groups, parallel slots, leaf file names and extensions, and
|
|
334
|
+
throws rather than guessing for files Next does not route.
|
|
335
|
+
|
|
336
|
+
## 1.0.0-next.0
|
|
337
|
+
|
|
338
|
+
- Added `@capacms/sdk/next`, the dependency-free `/api/` read client for `cap_`
|
|
339
|
+
keys, typed selects, cursor iteration, structured `/api/` errors, and
|
|
340
|
+
surrogate cache tags.
|
|
341
|
+
- Added `@capacms/sdk/nextjs` helpers for Next fetch caching, surrogate tag
|
|
342
|
+
construction, webhook revalidation, and server-only draft client selection.
|
|
343
|
+
- Kept the legacy `/v2/api` client as the root export.
|
|
344
|
+
- Added relation-aware `capa-codegen` output while preserving byte-identical
|
|
345
|
+
output for schemas without relations.
|