@mapled/next 0.6.0 → 0.7.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/README.md CHANGED
@@ -63,6 +63,16 @@ await mapled.getRecords("artcles"); // type error — no s
63
63
 
64
64
  Without a schema the client behaves as before: any key, `Record<string, unknown>` data, or the type you name per call (`getRecords<Article>("articles")`). `createAppClient<MapledSchema>` types live data the same way — `db.create("orders", data)` wants an `Order`. `mapled doctor` tells you when the generated file is behind the schema.
65
65
 
66
+ ### Renamed fields
67
+
68
+ When a field's key is renamed in Mapled, nothing breaks: the old key stays as an alias — delivered next to the new one, accepted in `filter`, `sort`, `fields`, `expand` and in live-data writes — until someone removes it in Field settings. Answers that still serve a previous key name it (`aliases: { products: { price: "amount" } }` on a list result), and outside production the client says so once per key:
69
+
70
+ ```
71
+ [mapled] “price” in “products” was renamed to “amount”. The old key keeps working until its alias is removed in Mapled — use “amount” instead.
72
+ ```
73
+
74
+ Move the code to the new key, run `mapled types generate` (the old key is typed `@deprecated` until then), and remove the alias. In production the client stays silent.
75
+
66
76
  ### Pin a release
67
77
 
68
78
  A page that makes several reads can pin them all to one release, so a publish landing mid-render can't mix two versions:
package/dist/index.d.ts CHANGED
@@ -51,6 +51,10 @@ export type ListResult<T = Record<string, unknown>> = {
51
51
  records: MapledRecord<T>[];
52
52
  total: number;
53
53
  release: number;
54
+ /** Renamed fields whose previous keys this answer still serves, by
55
+ collection: `{ products: { price: "amount" } }`. Absent when nothing
56
+ was renamed. Outside production the SDK warns about each once. */
57
+ aliases?: Record<string, Record<string, string>>;
54
58
  };
55
59
  export type ImageOptions = {
56
60
  /** Snapped up to the nearest preset (64 … 2560); never upscaled past the source. */
package/dist/index.js CHANGED
@@ -1,6 +1,34 @@
1
1
  /** Mapled delivery client for Next.js sites.
2
2
  Reads published content only — pair it with the revalidation webhook
3
3
  handler from "@mapled/next/server" for instant updates on publish. */
4
+ /** Renamed fields (previous keys): Mapled keeps serving a renamed field
5
+ under its old key — and accepting it in filters, sorts and writes —
6
+ until the alias is removed in Field settings, and names such keys in
7
+ its answers. Outside production each is reported once per process, so
8
+ the site moves to the new key before the alias goes. */
9
+ const KEY_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
10
+ const reported = new Set();
11
+ function reportAliases(body) {
12
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "production")
13
+ return;
14
+ const aliases = body?.aliases;
15
+ if (!aliases || typeof aliases !== "object")
16
+ return;
17
+ for (const [collection, keys] of Object.entries(aliases)) {
18
+ if (!keys || typeof keys !== "object" || !KEY_RE.test(collection))
19
+ continue;
20
+ for (const [previous, current] of Object.entries(keys)) {
21
+ // keys are the project's content: only what looks like a key is printed
22
+ if (typeof current !== "string" || !KEY_RE.test(previous) || !KEY_RE.test(current))
23
+ continue;
24
+ const id = `${collection}.${previous}`;
25
+ if (reported.has(id))
26
+ continue;
27
+ reported.add(id);
28
+ console.warn(`[mapled] “${previous}” in “${collection}” was renamed to “${current}”. The old key keeps working until its alias is removed in Mapled — use “${current}” instead.`);
29
+ }
30
+ }
31
+ }
4
32
  /** URL of an image or file value (an asset id) — the original, or a
5
33
  resized variant made on first request and cached from then on. */
6
34
  export function assetUrl(id, opts = {}) {
@@ -95,7 +123,9 @@ export function createClient(config) {
95
123
  const res = await fetch(`${base}${path}${qs ? `?${qs}` : ""}`, init);
96
124
  if (!res.ok)
97
125
  throw await failure(res);
98
- return { status: res.status, body: (await res.json()) };
126
+ const body = (await res.json());
127
+ reportAliases(body);
128
+ return { status: res.status, body };
99
129
  }
100
130
  /** expand / fields on every read. */
101
131
  const readParams = (search, opts) => {
@@ -198,7 +228,9 @@ export function createAppClient(config) {
198
228
  }
199
229
  throw new MapledError(res.status, message);
200
230
  }
201
- return (await res.json());
231
+ const body = (await res.json());
232
+ reportAliases(body);
233
+ return body;
202
234
  }
203
235
  const collectionPath = (c) => `/v1/app/collections/${encodeURIComponent(c)}/records`;
204
236
  const client = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapled/next",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Read published Mapled content in a Next.js site \u2014 delivery client, ISR tags, and a revalidation webhook handler.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://mapled.io",