ampless 1.0.0-beta.51 → 1.0.0-beta.53

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/dist/index.d.ts CHANGED
@@ -1829,17 +1829,31 @@ declare function escapeXml(s: string): string;
1829
1829
  *
1830
1830
  * Variable 'body' has an invalid value.
1831
1831
  *
1832
- * On the read side two wire shapes coexist:
1833
- *
1834
- * - JSON-encoded string — what the auto-generated CRUD resolver and
1835
- * custom resolvers usually return.
1836
- * - Native object / Map DynamoDBDocumentClient unmarshals
1837
- * AWSJSON-stored maps straight into JS objects when read directly
1838
- * from DynamoDB (the path used by the trusted processor and the
1839
- * MCP Lambda).
1840
- *
1841
- * `decodeAwsJson` handles both: pass strings through `JSON.parse`,
1842
- * everything else as-is.
1832
+ * On the read side there are two FUNDAMENTALLY DIFFERENT paths, and they
1833
+ * must be handled differently — the value's runtime shape is NOT enough
1834
+ * to disambiguate them:
1835
+ *
1836
+ * 1. GraphQL wire read (auto-generated CRUD resolver, custom resolvers,
1837
+ * raw GraphQL fetch) the value arrives as a JSON-encoded string,
1838
+ * regardless of the underlying type. Use `decodeAwsJson` to parse it
1839
+ * back into the native JS value.
1840
+ *
1841
+ * 2. Direct DynamoDBDocumentClient read (the trusted processor and the
1842
+ * MCP Lambda read straight from DynamoDB) — DocumentClient already
1843
+ * unmarshals AWSJSON-backed attributes into native JS types
1844
+ * (S→string, N→number, BOOL→boolean, M→object). The value is ALREADY
1845
+ * the correct JS type and must be used AS-IS. Do NOT run
1846
+ * `decodeAwsJson` / `JSON.parse` on it.
1847
+ *
1848
+ * Why the distinction is load-bearing: a native scalar STRING from path 2
1849
+ * is indistinguishable, by type alone, from a wire string on path 1. But
1850
+ * `decodeAwsJson("1470")` === `JSON.parse("1470")` === the number `1470`,
1851
+ * so running the decoder on a DocumentClient scalar string silently
1852
+ * double-decodes numeric-looking settings/bodies (this caused a
1853
+ * site-wide 500). The "non-strings pass through unchanged" tolerance of
1854
+ * `decodeAwsJson` does NOT make it safe on DocumentClient reads — scalar
1855
+ * strings are exactly the case it corrupts. Pick the decoder by read PATH,
1856
+ * never by the value's runtime shape.
1843
1857
  */
1844
1858
  /**
1845
1859
  * Serialise a value for an AWSJSON variable. `undefined` / `null` both
@@ -1848,9 +1862,14 @@ declare function escapeXml(s: string): string;
1848
1862
  */
1849
1863
  declare function encodeAwsJson(value: unknown): string;
1850
1864
  /**
1851
- * Deserialise an AWSJSON value from a GraphQL / DynamoDB read.
1852
- * Tolerates both the wire-string shape and the auto-unmarshalled
1853
- * native value. Throws if the string is not valid JSON.
1865
+ * Deserialise an AWSJSON value from a GraphQL wire read (path 1 above).
1866
+ * Non-string inputs pass through unchanged; strings go through
1867
+ * `JSON.parse` and throw if not valid JSON.
1868
+ *
1869
+ * Only call this on values read over the GraphQL wire. Do NOT call it on
1870
+ * values read directly via DynamoDBDocumentClient — those are already
1871
+ * native JS types, and a native scalar string (e.g. "1470") would be
1872
+ * double-decoded into a number. See the module doc block above.
1854
1873
  */
1855
1874
  declare function decodeAwsJson(value: unknown): unknown;
1856
1875
 
@@ -481,6 +481,15 @@ runtime は `body` を `sanitize-html` の厳格 allowlist で sanitize し(
481
481
 
482
482
  `cms.config.plugins` の順序は集約後も保たれます。
483
483
 
484
+ > **`publicHead` / `publicBodyEnd` はいつ描画される?**
485
+ > runtime は、ampless middleware が処理した公開リクエストでのみ
486
+ > これらのサーフェスの出力を描画します。`/admin`、`/login`、
487
+ > そして theme preview リクエスト(`?previewTheme=` /
488
+ > `?previewColorScheme=` iframe)では描画されません。これにより、
489
+ > GTM / GA / consent script が admin page view や live preview traffic で
490
+ > analytics を汚染することを防ぎます。この挙動は
491
+ > `@ampless/runtime` の npm update だけで反映され、サイトコードの変更は不要です。
492
+
484
493
  ### `publicBodyForPost` の使用例(Phase 4)
485
494
 
486
495
  `schema` capability を宣言してサーフェスを実装します:
@@ -603,6 +603,16 @@ interpolates that fragment directly:
603
603
  `cms.config.plugins` iteration order is preserved across the
604
604
  collected list.
605
605
 
606
+ > **When are `publicHead` / `publicBodyEnd` rendered?**
607
+ > The runtime renders output from these surfaces only on public requests
608
+ > that have been processed by the ampless middleware. They are **not**
609
+ > rendered under `/admin`, `/login`, or on theme-preview requests
610
+ > (`?previewTheme=` / `?previewColorScheme=` iframe). This prevents GTM,
611
+ > GA, and consent scripts from polluting analytics with admin page views
612
+ > or live-preview traffic. An npm update to `@ampless/runtime` is
613
+ > sufficient to pick up this behaviour — no changes to site code are
614
+ > required.
615
+
606
616
  ### `publicBodyForPost` example (Phase 4)
607
617
 
608
618
  Declare the `schema` capability and implement the surface:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ampless",
3
- "version": "1.0.0-beta.51",
3
+ "version": "1.0.0-beta.53",
4
4
  "description": "Serverless CMS for AWS Amplify",
5
5
  "license": "MIT",
6
6
  "type": "module",