@alchemy_cms/json_api 3.0.0 → 3.0.1

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
@@ -61,11 +61,37 @@ const pages = deserializePages(data)
61
61
  console.log(pages[0].name) // => Homepage
62
62
  ```
63
63
 
64
+ ## HTTP Caching
65
+
66
+ Alchemy::JsonApi allows for caching API responses. It respects the caching configuration of your Rails app and of your Alchemy configuration and settings in the pages page layout configuration. Restricted pages are never cached.
67
+
68
+ By default it sets the `max-age` `Cache-Control` header to 10 minutes (`600` seconds). You can change this by configuring the `Alchemy::JsonApi.page_cache_max_age` setting. It is recommended to set this via an environment variable like this:
69
+
70
+ ```rb
71
+ # config/initializers/alchemy_json_api.rb
72
+ Alchemy::JsonApi.page_cache_max_age = ENV.fetch("ALCHEMY_JSON_API_CACHE_DURATION", 600).to_i
73
+ ```
74
+
75
+ ### Edge Caching
76
+
77
+ Alchemy sets the `must-revalidate` directive if caching is enabled. If your CDN supports it, you can change that to use the much more efficient `stale-while-revalidate` directive by changing the `Alchemy::JsonApi.page_caching_options` setting to any integer value.
78
+
79
+ ```rb
80
+ # config/initializers/alchemy_json_api.rb
81
+ Alchemy::JsonApi.page_caching_options = {
82
+ stale_while_revalidate: ENV.fetch("ALCHEMY_JSON_API_CACHE_STALE_WHILE_REVALIDATE", 60).to_i
83
+ }
84
+ ```
85
+
86
+ > [!TIP]
87
+ > You can set any caching option that [`ActionController::ConditionalGet#expires_in` supports](https://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-expires_in), like `stale_if_error`, `public` or `immutable`.
88
+
64
89
  ## Key transforms
65
90
 
66
91
  If you ever want to change how Alchemy serializes attributes you can set
67
92
 
68
93
  ```rb
94
+ # config/initializers/alchemy_json_api.rb
69
95
  Alchemy::JsonApi.key_transform = :camel_lower
70
96
  ```
71
97
 
@@ -1,25 +1,24 @@
1
- import { deserialize as d } from "./deserialize.js";
1
+ import { deserialize as r } from "./deserialize.js";
2
2
  function n(t) {
3
3
  const s = [];
4
4
  return t.forEach((e) => {
5
- var r, i, c;
6
- ((r = e.nested_elements) == null ? void 0 : r.length) > 0 && (e.nested_elements = n(
5
+ e.nested_elements?.length > 0 && (e.nested_elements = n(
7
6
  e.nested_elements
8
- )), ((i = e.nestedElements) == null ? void 0 : i.length) > 0 && (e.nestedElements = n(e.nestedElements)), ((c = e.essences) == null ? void 0 : c.length) > 0 && (e.essences = e.essences.filter((f) => !f.deprecated)), e.deprecated || s.push(e);
7
+ )), e.nestedElements?.length > 0 && (e.nestedElements = n(e.nestedElements)), e.essences?.length > 0 && (e.essences = e.essences.filter((i) => !i.deprecated)), e.deprecated || s.push(e);
9
8
  }), s;
10
9
  }
11
- function o(t) {
12
- const s = d(t);
10
+ function d(t) {
11
+ const s = r(t);
13
12
  return s.elements = n(s.elements), s;
14
13
  }
15
- function l(t) {
16
- const s = d(t);
14
+ function f(t) {
15
+ const s = r(t);
17
16
  return s.forEach((e) => {
18
17
  e.elements = n(e.elements);
19
18
  }), s;
20
19
  }
21
20
  export {
22
- d as deserialize,
23
- o as deserializePage,
24
- l as deserializePages
21
+ r as deserialize,
22
+ d as deserializePage,
23
+ f as deserializePages
25
24
  };
@@ -1,45 +1,44 @@
1
- import y from "@ungap/structured-clone";
2
- function A(e, r = {}) {
3
- const s = y(e);
4
- r || (r = {});
5
- const n = s.included || [];
6
- return Array.isArray(s.data) ? s.data.map((i) => f(i, n, !1)) : f(
1
+ function y(e, t = {}) {
2
+ const s = structuredClone(e);
3
+ t || (t = {});
4
+ const o = s.included || [];
5
+ return Array.isArray(s.data) ? s.data.map((i) => f(i, o, !1)) : f(
7
6
  s.data,
8
- n,
7
+ o,
9
8
  !1
10
9
  );
11
10
  }
12
- function f(e, r, s, n) {
13
- if (r.cached || (r.cached = {}), e.type in r.cached || (r.cached[e.type] = {}), s && e.id in r.cached[e.type])
14
- return r.cached[e.type][e.id];
15
- const t = e.attributes || {};
16
- if (t.id = e.id, r.cached[e.type][e.id] = t, e.relationships)
11
+ function f(e, t, s, o) {
12
+ if (t.cached || (t.cached = {}), e.type in t.cached || (t.cached[e.type] = {}), s && e.id in t.cached[e.type])
13
+ return t.cached[e.type][e.id];
14
+ const r = e.attributes || {};
15
+ if (r.id = e.id, t.cached[e.type][e.id] = r, e.relationships)
17
16
  for (const c of Object.keys(e.relationships)) {
18
- const o = e.relationships[c];
19
- if (Array.isArray(o.data)) {
17
+ const n = e.relationships[c];
18
+ if (Array.isArray(n.data)) {
20
19
  const p = [];
21
- o.data.forEach((a) => {
20
+ n.data.forEach((a) => {
22
21
  const h = u(
23
- r,
22
+ t,
24
23
  a.type,
25
24
  a.id
26
25
  );
27
26
  p.push(h);
28
- }), t[c] = p;
29
- } else o && o.data ? t[c] = u(
30
- r,
31
- o.data.type,
32
- o.data.id
33
- ) : t[c] = null;
27
+ }), r[c] = p;
28
+ } else n && n.data ? r[c] = u(
29
+ t,
30
+ n.data.type,
31
+ n.data.id
32
+ ) : r[c] = null;
34
33
  }
35
- return t;
34
+ return r;
36
35
  }
37
- function u(e, r, s, n) {
36
+ function u(e, t, s, o) {
38
37
  let i = null;
39
- return e.forEach((t) => {
40
- t.type === r && t.id === s && (i = f(t, e, !0));
38
+ return e.forEach((r) => {
39
+ r.type === t && r.id === s && (i = f(r, e, !0));
41
40
  }), i || (i = { id: s }), i;
42
41
  }
43
42
  export {
44
- A as deserialize
43
+ y as deserialize
45
44
  };
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@alchemy_cms/json_api",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "JSON API deserializer for AlchemyCMS",
5
5
  "license": "BSD-3-Clause",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/AlchemyCMS/alchemy-json_api.git"
9
9
  },
10
+ "engines" : {
11
+ "node" : ">=20.19.0"
12
+ },
10
13
  "keywords": [
11
14
  "AlchemyCMS",
12
15
  "json:api",
@@ -23,12 +26,9 @@
23
26
  "files": [
24
27
  "dist"
25
28
  ],
26
- "dependencies": {
27
- "@ungap/structured-clone": "^1.0.1"
28
- },
29
29
  "devDependencies": {
30
30
  "prettier": "^3.3.3",
31
- "vite": "^6.3.5",
31
+ "vite": "^7.0.4",
32
32
  "vitest": "^3.2.4"
33
33
  },
34
34
  "scripts": {