@relyio/sdk 0.13.0 → 0.14.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/dist/{chunk-3NPPMGB6.js → chunk-5UMY6CS4.js} +2 -2
  3. package/dist/{chunk-6NGJXLOR.js → chunk-DBBZVZOS.js} +968 -2681
  4. package/dist/{chunk-DEDIJKHY.cjs → chunk-GUPV2M3X.cjs} +969 -2691
  5. package/dist/{chunk-EW23SZPX.js → chunk-PCFTJLEP.js} +540 -262
  6. package/dist/{chunk-Z6GLWSSD.cjs → chunk-RSHMA4KT.cjs} +2 -2
  7. package/dist/{chunk-FOSM4LMM.cjs → chunk-X4KSS7PP.cjs} +539 -262
  8. package/dist/client/index.cjs +3 -3
  9. package/dist/client/index.d.cts +3 -3
  10. package/dist/client/index.d.ts +3 -3
  11. package/dist/client/index.js +1 -1
  12. package/dist/{include-paths-Bs5FhNw2.d.cts → define-content-type-BUZeWtpk.d.cts} +3657 -2594
  13. package/dist/{include-paths-Cb7iPCW2.d.ts → define-content-type-DOrZb_a_.d.ts} +3657 -2594
  14. package/dist/{define-schema-UHViXKiv.d.ts → define-schema-5aHmsA8j.d.ts} +238 -356
  15. package/dist/{define-schema-sWJ8Zn7C.d.cts → define-schema-nCfZeboB.d.cts} +238 -356
  16. package/dist/{index-8DozAWsA.d.ts → index-B97ZDj44.d.ts} +2 -2
  17. package/dist/{index--_u1nPHv.d.cts → index-C-pcllqY.d.cts} +2 -2
  18. package/dist/index-DOhFQbv7.d.ts +3065 -0
  19. package/dist/index-DgVV5Nj7.d.cts +3065 -0
  20. package/dist/index.cjs +90 -130
  21. package/dist/index.d.cts +16 -23
  22. package/dist/index.d.ts +16 -23
  23. package/dist/index.js +4 -4
  24. package/dist/rich-text/index.cjs +11 -11
  25. package/dist/rich-text/index.d.cts +2 -2
  26. package/dist/rich-text/index.d.ts +2 -2
  27. package/dist/rich-text/index.js +1 -1
  28. package/dist/schema/index.cjs +33 -37
  29. package/dist/schema/index.d.cts +33 -18
  30. package/dist/schema/index.d.ts +33 -18
  31. package/dist/schema/index.js +1 -1
  32. package/dist/types/index.d.cts +1 -1
  33. package/dist/types/index.d.ts +1 -1
  34. package/package.json +2 -2
  35. package/dist/index-BT0L8xJj.d.cts +0 -3717
  36. package/dist/index-CPjJ25R4.d.ts +0 -3717
package/CHANGELOG.md CHANGED
@@ -1,5 +1,149 @@
1
1
  # @relyio/sdk
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 133e573: **0.14: one way to say each thing.** A schema is a set of keyed records, every read takes one options object, a version-checked write takes the entry you read, and search pages by number with a total. This is a breaking release: every old signature is removed, with no aliases and no deprecation window, so each old call fails to compile and you find them all at once. Only the TypeScript authoring changes — what deploys, is stored and is hashed is the same, so YAML schemas and their schema hashes are unchanged (except the legacy list form of `localization`, below).
8
+
9
+ ## Defining a schema
10
+
11
+ The key is the id everywhere. Write each declaration under its key in `defineSchema`, with no id of its own; only `fieldset('id', …)` and `defineLocale(code, …)` keep theirs.
12
+
13
+ ```ts
14
+ // 0.13
15
+ const post = defineContentType('post', {
16
+ displayName: 'Post',
17
+ fields: [
18
+ fields.shortText('title', {
19
+ config: { required: true },
20
+ ui: { displayName: 'Title' },
21
+ localization: true,
22
+ }),
23
+ fields.enum('status', { config: { options: [{ value: 'draft', label: 'Draft' }] } }),
24
+ fields.object('seo', {
25
+ config: { of: { id: 'seo', displayName: 'SEO', fields: [fields.shortText('metaTitle')] } },
26
+ }),
27
+ ],
28
+ })
29
+
30
+ // 0.14
31
+ const seo = fieldset('seo', { displayName: 'SEO', fields: { metaTitle: fields.shortText() } })
32
+ const post = defineContentType({
33
+ fields: {
34
+ title: fields.shortText({ required: true, localized: true }),
35
+ status: fields.enum({ options: { draft: 'Draft' } }),
36
+ seo: fields.object({ of: seo }),
37
+ },
38
+ })
39
+ export const schema = defineSchema({ contentTypes: { post } })
40
+ ```
41
+
42
+ | Removed | Write instead |
43
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
44
+ | An id passed to `defineContentType`, `defineSingleton`, `defineAssetType`, `defineSettingsGroup`, `defineQuery`, `defineRole`, `defineView`, `defineWorkflowStage` | `key: defineX({ … })` under its section in `defineSchema` (`roles`, `views`) or `defineWorkflow({ stages })` |
45
+ | An id passed to a Field builder, `fields.shortText('title', …)` | `title: fields.shortText({ … })` in the type's `fields` record |
46
+ | `fields` as a list; `roles`, `views` and workflow `stages` as lists | Records, in the order the form shows them |
47
+ | `config: { … }` on a Field | Its keys beside the Field's other options: `fields.shortText({ required: true, maxLength: 120 })` |
48
+ | `ui: { displayName, description }` | `displayName` and `description` beside `ui`; `ui` holds only the editor widget's options |
49
+ | `localization: true \| { enabled, requiredLocales, fallback }` | `localized: true \| { requiredLocales, fallback }` (YAML keeps `localization`) |
50
+ | Enum options as `[{ value, label }]` | A value-to-label map, `{ draft: 'Draft', live: 'Live' }`, its key order the display order. A whole-number value (`'1'`) is refused: write `'v1'` |
51
+ | A bare `{ id, displayName, fields }` object as a Fieldset | `fieldset('id', { fields: { … } })` — in a Section, an `of`, a rich-text Block or Inline element |
52
+ | A fieldset's `collapsedByDefault` | `collapsed` |
53
+ | The types `ContentTypeConfig`, `SingletonConfig`, `AssetTypeConfig`, `SettingsGroupConfig`, `WorkflowConfig` | `KeyedContentTypeConfig`, `KeyedSingletonConfig`, `KeyedAssetTypeConfig`, `KeyedSettingsGroupConfig`, `KeyedWorkflowConfig` |
54
+ | `defineSingletonContentType` and its type `InferSingletonContentType`, the long names of one function | `defineSingleton` and `InferSingleton` |
55
+
56
+ - **Labels are derived from keys.** `displayName` is optional on types, Fields, fieldsets, roles and stages: `pageSettings` reads "Page settings". A Field written without a label now deploys the derived one, so a schema that left labels out deploys with a different hash once, adding them. `displayNamePlural` is not derived.
57
+ - **Names that point elsewhere are checked as you type.** A reference's `to` and rich text's `links.to` against the schema's content, singleton and asset types; a locale's `fallback` and a Field's `requiredLocales` against the declared locales; `displayField` against the type's own Fields; a stage's roles against the built-in and declared roles; a type's `workflow.stages` against the workflow's stages. A typo fails to compile at the key that holds it.
58
+ - **Refused at `defineSchema`:** one definition registered under two keys, a Section whose key differs from its fieldset's id, and one Field id used twice across a type's Sections (naming both paths).
59
+ - A JavaScript caller still writing the old form is refused at runtime, naming the builder and what to write, rather than deploying a malformed definition.
60
+ - **The legacy list form of `localization` is gone everywhere** — TypeScript, YAML and the stored definition: a list (`localization: ['en', 'fr']`) is refused at deploy with one error at that Field saying what to write.
61
+ - `relyio generate-types` writes the keyed form, and the header of the file it writes reads with `list()`.
62
+ - `relyio deploy` and `relyio diff` say when a removed type and an added one look like a rename (same Fields), beside the counts: `looks renamed to <type>`. The deploy plan's `type-removed` change carries `probableRenameTo`.
63
+ - The CLI's blog template labels its two `seo` objects "SEO".
64
+
65
+ ## Reading
66
+
67
+ Every read takes one options object, on every handle — `content(type)`, `asset(type)`, `singleton(key)`, `settings(group)` — and in React and Next alike.
68
+
69
+ | Removed | Write instead |
70
+ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
71
+ | `content(t).query()…execute()`, `fetch(options)` | `list(options)` → the API's `{ data, page }` |
72
+ | `findById(id)…execute()`, `fetchOne(id, options)` | `get(idOrSlug, options)` → the entry or `null` |
73
+ | `fetchAll(locale?)` | `for await (const entry of listAll(options))`, or `Array.fromAsync(listAll())` |
74
+ | `fetchFirst(where, locale)` | `(await list({ where, locale, limit: 1 })).data[0] ?? null` |
75
+ | `exists(id)` | `(await get(id)) !== null` |
76
+ | `fetchOneWithTag(id)` | `get(id)`: the check travels in the entry's `_metadata` |
77
+ | `ofType(type)` | `client.content(type)` |
78
+ | `withLocale(locale)` — on the client and on a handle | `{ locale }` on the call, or `client.with({ locale, dataset })` |
79
+ | A handle's `getContentType()`, `getAssetType()`, `getSingletonKey()`, `getGroupId()`, `getDefaultLocale()` | The name you passed; `client.getLocale()` for the locale |
80
+ | `asset(t).query()`, `findById`, `fetchOne`, `fetchFirst` | `asset(t).list`, `get`, `listAll`, beside `create`, `file(uid)` and `upload(file)` |
81
+ | `singleton(k).fetch()`, `fetchWithTag()`, `exists()`, the fluent `include()`/`locale()`/`reset()` | `singleton(k).get({ include, locale, dataset, fresh })` → the singleton or `null` |
82
+ | `settings(g).fetch()`, `fetchWithTag()`, `exists()`, `include()`/`locale()`/`resetOptions()` | `settings(g).get(options)` (never `null`: a declared group answers its defaults) |
83
+ | `client.search(q)` chained builder (`.in()`, `.across()`, `.where()`, `.sort()`, `.fields()`, `.execute()`) | `client.search(q, { contentType, where, searchFields, select, sort, page, limit, locale, dataset, fresh, … })` |
84
+ | `client.autocomplete(q)` and `client.similar(id)` builders | `client.autocomplete(q, { contentType, field, … })`, `client.similar(id, { contentType, limit, … })` |
85
+ | `client.adhoc()`, `client.query.execute/build/fetch/fetchSingleton/aggregate` | `client.query({ from, where, include, select, sort, limit, page, locale, aggregate, params, fullText })` |
86
+ | `client.executeQuery(name, params)` | `client.query(name, { params })` — by name alone (`POST /v1/queries/{name}`), no schema needed |
87
+ | `client.getSchemaInfo(type?)` | `client.schema(type?)` (the client's `schema` getter, which handed back the local definition, is gone) |
88
+ | Per-call `headers` | `client.with({ dataset })`, `create`'s `dataset`, or client-level `headers` |
89
+ | `version(id, n, { locale })`, a singleton's or group's `version(n)` | `version(id, { version: n, locale })`, `version({ version: n, locale })` |
90
+ | `restore(id, n, locale, { ifMatch })` | `restore(entry, { version: n })` (checked) or `restore(id, { version: n, locale })` (unchecked) |
91
+ | Classes `ContentQueryBuilder`, `ContentByIdBuilder`, `SearchClient`, `SearchBuilder`, `AutocompleteBuilder`, `SimilarBuilder`, `BatchClient`, `BatchBuilder`, `AdhocQueryClient`, `AdhocQueryBuilder`, and their types (`ContentFetchOptions`, `SingletonFetchOptions`, `SettingsFetchOptions`, `ExtendedQueryResult`, `ContentQueryResult`, `QueryOptions`, `SortOptions`, `SearchMode`, `SearchFilter`, `SearchFields`, `SearchSort`, `BatchMethod`, `BatchOperation`, `BatchOptions`, `AdhocQueryMethods`, `AdhocQueryDefinition`, `AdhocQueryOptions`, `AdhocQueryResult`, `AdhocFetchBlock`, `AdhocAggregateBlock`, `AdhocSearchBlock`, `FilterValue`, `FullTextConfig`) | The calls above, typed by `ListOptions`, `GetOptions`, `ListAllOptions`, `DocumentReadOptions`, `EntryList`, `SortOption`, `SearchOptions`, `SearchWhere`, `AdhocQuery`, `QueryAnswer`, `BatchWrite`, `BatchWriteOptions`, `BatchBody` |
92
+ | `client.ready()`, `testConnection()`, `getLocales()`, `getDefaultLocale()`, `listContentTypes()` | `health()` (rejects when the API cannot serve), `locales()` (each marked `default`), `contentTypes()` |
93
+
94
+ One name per option:
95
+
96
+ - **Paging:** `limit`, plus `cursor` (to walk; `page.nextCursor`) or `page` (an archive page like `/blog/page/3`). `offset` and `pageSize` are gone; a list carries no total and a page-number read runs no count.
97
+ - **`sort`:** an object whose key order is the priority, `{ featured: 'desc', publishedAt: 'desc' }`, its keys checked against the type.
98
+ - **`select`:** the entry's own Fields, checked; an expanded reference's Fields are picked in its include path, `'author(name)'`. It replaces `select()` and `fields()`.
99
+ - **`locale`:** a code, a list of codes or `'*'`, checked against the declared locales; the read's type gains `localizations` only for a list or `'*'`. A per-call locale replaces the client's.
100
+ - **`dataset`:** per call, sent as that request's `X-RelyIO-Dataset`.
101
+ - **`fresh`:** `fresh: '<cursor>'` keeps meaning "no older than this change"; `fresh: true` reads past every cache (`Cache-Control: no-cache`) for a write flow after a conflict.
102
+ - **`children`:** `true`, or `{ depth: 1 | 2 | 3, limit }`. `ChildrenOptions.contentTypes`, which never worked, is gone, and an unknown `?children=` value is a 400.
103
+ - **`where`:** a list's `where` now refuses two spellings it used to accept: an operator written without its `$` (`{ price: { gte: 10 } }`) and an unknown key beside an operator (`{ price: { $gte: 10, max: 20 } }`) are each a 400 naming the key — write `$gte`, and one operator per key. The query language — saved queries, the search `where`, the ad-hoc query — now reads the same `$`-prefixed `where` a list takes, parsed by one read core: `$eq $ne $gt $gte $lt $lte $in $nin $contains $startsWith $endsWith $exists $isNull $inTheLast $inTheNext`, and refuses the same two spellings. `$startsWith` and `$endsWith` match case; `notExists` is gone (`{ $exists: false }`). A search's and an autocomplete's `where` are typed as a list's. A saved query written with the bare dialect must be rewritten and redeployed. Each operator now means in a saved query's fetch and aggregate `where` exactly what it means in a list, since the same read core compiles them: `$isNull` on a reference inside a block is "no item holds one", where a saved query used to ask whichever item it read first. A refused operator object is refused in the same words by a list and a query.
104
+ - **Not found:** `get` returns `null` only when the API's not-found answer names the entry. A content type, singleton or schema nobody deployed throws `ResourceNotFoundError` naming which. `version()`, on every handle, answers the version or throws `ResourceNotFoundError` naming what is missing — the version, the entry or document, its type or the schema; a singleton's and a settings group's no longer answer `null`.
105
+ - **`children(id, options)`** takes `get`'s options — `include` checked against the type, `locale` as a code, a list or `'*'`, `dataset`, `fresh`, `children` — and its children are typed as `get` types an entry.
106
+
107
+ `client.with({ locale, dataset })` returns a client with those defaults that otherwise follows its parent: its key, base URL and every later configuration change. `versionCheckOf(entry)` is exported for building a check yourself.
108
+
109
+ ## Writing
110
+
111
+ - **A version check comes from the entry you read.** `update(entry, data)`, `delete(entry)` and `restore(entry, { version })` check the version the entry's `_metadata` carries — present whether or not a cache served the read — in the locale it was read in, so a read negotiated from `Accept-Language` is written back to that locale. A stale write throws `ResourceConflictError` naming the versions that disagreed and saying to re-read with `fresh: true` and retry. `update(id, data)` and `delete(id)` write unchecked, on purpose. No write takes `ifMatch`; `entityTagOf` and `ConditionalWriteOptions` are gone, and the SDK no longer reads the `X-Entity-Tag` header (the API still sends it for plain-HTTP callers).
112
+ - **The `If-Match` tag is four parts:** `uid:locale:localeVersion:sharedVersion`; a three-part tag is refused 400. `_metadata.sharedVersion` carries the shared-field counter, so a check from the body is as strong as one from the header. A locale with no version yet reports version 0, and a check at 0 means "this locale must not exist yet". A stale check is 409. `DELETE` is checked too.
113
+ - **A singleton's or a settings group's write:** `update(read, data)` checked, `update(data, { locale, idempotencyKey })` unchecked; a group's `reset(read)` / `reset({ locale, idempotencyKey })`. The positional `update(data, locale, options)` and `reset(locale, options)` are gone. An unchecked write's data carries no `_metadata`: a value that does is a read, and the checked form takes it.
114
+ - **Batches are one call:** `client.batch([{ create }, { update, entry | id }, { replace, entry | id }, { delete, entry | id }, { singleton }], { atomic, dryRun, stopOnError, returnData, dataset })` → `{ data: { results, summary } }`. An entry checks the operation as `update(entry)` does. The chained `client.batch()` builder is gone. A whole-entry replace is written only here, `{ replace, entry }`: a handle offers `update` and `delete`, and there is no single-entry replace route.
115
+ - `create(data, { slug, locale, parentId, sortOrder, dataset, idempotencyKey })` takes `dataset` in place of per-call `headers`.
116
+ - **Customer writes go live in the locale they name.** A write to a locale the entry has never had publishes it, at version 1; on an entry published in no locale, that locale is published while the default stays a draft. An asset's new locale is published once the file it reads is ready. A customer restore of a published locale goes live. A write refused because an editor has a pending Studio draft says so.
117
+ - An asset update honours its `If-Match` and `Idempotency-Key`.
118
+
119
+ ## Search
120
+
121
+ `search(q, { page, limit })` pages by number and answers `page: { number, limit, total, pageCount }`: `total` counts every match, so "page 2 of 3" needs no arithmetic. `offset` is refused. A hybrid search pages within one fused ranking window, the top 500 of each leg fused once, and its `total` is that window's size, so pages agree across numbers. `autocomplete` and `similar` take one options object.
122
+
123
+ ## The Content API (`api.relyio.com`)
124
+
125
+ - `GET /v1/{contentType}` no longer declares `pageSize`, `withCount` or `contentType`: each is a 400 naming it. `limit` is the one page size.
126
+ - A declared singleton nobody has written answers 404 with `details.kind: 'entry'`; an undeclared one stays `kind: 'singleton'`. The singleton route no longer declares `?locales=`.
127
+ - `GET /v1/{contentType}/{id}` answers an entry of that type only; an entry of another type is not found.
128
+ - `GET` and `POST /v1/queries/{name}` run a saved query by name, its parameters checked against the declaration (an undeclared one is refused, naming it). `queries` is a reserved type id.
129
+ - The ad-hoc query (`POST /v1/query`, `client.query({ from, … })`) takes list's option names for what its route serves today: `page` with `limit` (no `cursor`), one `locale`, and `select` or `include` but not both. Cursor paging, locale lists and `select` beside `include` arrive with a later release (REL-2460).
130
+
131
+ ## React (`@relyio/react`)
132
+
133
+ `useEntries`, `useEntry`, `useSingleton`, `useSearch` and `relyioQueryOptions()` take exactly the core's options and return its results; hook names are unchanged. React's own option shapes — `EntriesReadInput`, `EntryReadInput`, `SingletonReadInput`, `SearchReadInput`, a `sort` list, `fields`, `offset` — are deleted. An untyped `useSingleton` answers `BaseSingleton | null`. Reads are keyed by dataset as well as locale. The `@relyio/sdk` peer is `>=0.14.0`.
134
+
135
+ ## Next (`@relyio/next`)
136
+
137
+ `createNextClient` keeps tagging every read under the new options. Tags name the request's dataset (a read's `dataset` or `with({ dataset })`), so a publish in another dataset evicts what was read there; `fresh: true` fetches with `cache: 'no-store'` and no tags. `ReferenceTargetsPort` gained a `dataset` parameter. Reference targets are read with `client.schema(type)`. The `@relyio/sdk` peer is `>=0.14.0`.
138
+
139
+ ## Toolbar (`@relyio/toolbar`)
140
+
141
+ A preview whose content type is not deployed settles `unreadable`, naming why, instead of `not-found`; a missing entry is still `not-found`. The `@relyio/sdk` peer is `>=0.14.0`.
142
+
143
+ ## Agents (`@relyio/agents`)
144
+
145
+ The tools and their manifest are unchanged. Inside them: `searchEntries` and `countEntries` honour `$startsWith`, `$endsWith` (case-sensitive) and `$isNull`; an edit by key's `PATCH` names the locale it read; an entry that is not there is refused as `RESOURCE_NOT_FOUND` `kind: 'entry'` in the tool's own words; `proposeCreateEntries`' batch leaves out the API's defaults (`dryRun`, `continueOnError`). The client type the tools take picks `schema` and carries `with`. The `@relyio/sdk` peer is `>=0.14.0`.
146
+
3
147
  ## 0.13.0
4
148
 
5
149
  ### Minor Changes
@@ -1088,5 +1088,5 @@ function escapeLineStarts(paragraph) {
1088
1088
  __name(escapeLineStarts, "escapeLineStarts");
1089
1089
 
1090
1090
  export { RICH_TEXT_VOID_TAGS, entryHeadingAnchors, escapeHtml, formatKeyPath, isDeclaredRichTextNode, parseKeyPath, relyioField, renderRichText, richTextHeadingAnchors, richTextHeadingSlug, richTextToHtml, richTextToMarkdown, safeRichTextHref };
1091
- //# sourceMappingURL=chunk-3NPPMGB6.js.map
1092
- //# sourceMappingURL=chunk-3NPPMGB6.js.map
1091
+ //# sourceMappingURL=chunk-5UMY6CS4.js.map
1092
+ //# sourceMappingURL=chunk-5UMY6CS4.js.map