@nuasite/cms 0.43.0-beta.1 → 0.43.0-beta.2

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/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "directory": "packages/astro-cms"
15
15
  },
16
16
  "license": "Apache-2.0",
17
- "version": "0.43.0-beta.1",
17
+ "version": "0.43.0-beta.2",
18
18
  "module": "src/index.ts",
19
19
  "types": "src/index.ts",
20
20
  "type": "module",
@@ -26,8 +26,10 @@
26
26
  }
27
27
  },
28
28
  "dependencies": {
29
- "@nuasite/cms-core": "0.43.0-beta.1",
30
- "@nuasite/cms-types": "0.43.0-beta.1",
29
+ "@nuasite/cms-core": "0.43.0-beta.2",
30
+ "@nuasite/cms-types": "0.43.0-beta.2",
31
+ "@nuasite/cms-sidecar": "0.43.0-beta.2",
32
+ "@nuasite/collections-admin": "0.43.0-beta.2",
31
33
  "@astrojs/compiler": "^3.0.1",
32
34
  "@babel/parser": "^7.29.2",
33
35
  "node-html-parser": "^7.1.0",
@@ -35,6 +37,10 @@
35
37
  },
36
38
  "devDependencies": {
37
39
  "@babel/types": "^7.29.0",
40
+ "@types/react": "^19.2.7",
41
+ "@types/react-dom": "^19.2.3",
42
+ "react": "^19.2.1",
43
+ "react-dom": "^19.2.1",
38
44
  "@milkdown/core": "^7.20.0",
39
45
  "@milkdown/ctx": "^7.20.0",
40
46
  "@milkdown/plugin-listener": "^7.20.0",
@@ -65,11 +71,19 @@
65
71
  "astro": "6.1.4",
66
72
  "typescript": "^6.0.2",
67
73
  "vite": "^7.0.0",
68
- "@aws-sdk/client-s3": "^3.0.0"
74
+ "@aws-sdk/client-s3": "^3.0.0",
75
+ "react": "^19.0.0",
76
+ "react-dom": "^19.0.0"
69
77
  },
70
78
  "peerDependenciesMeta": {
71
79
  "@aws-sdk/client-s3": {
72
80
  "optional": true
81
+ },
82
+ "react": {
83
+ "optional": true
84
+ },
85
+ "react-dom": {
86
+ "optional": true
73
87
  }
74
88
  },
75
89
  "scripts": {
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Local `/_nua/admin` SPA entry (cms-headless F7).
3
+ *
4
+ * Mounts the host-agnostic `@nuasite/collections-admin` SPA into the page served
5
+ * by the local-admin dev middleware. The only host-specific input is `apiBase`,
6
+ * which the HTML shell injects as `window.__NUA_ADMIN_API_BASE__` — it points at
7
+ * the in-process cms-sidecar mounted by the dev middleware (`…/cms/v1`). The same
8
+ * lib backs the webmaster Collections tab; only `apiBase` differs.
9
+ *
10
+ * This file is served as a virtual module through Astro's Vite dev server, so it
11
+ * is transformed (TSX → JS, React resolved) and HMR-capable like any app module.
12
+ */
13
+
14
+ import { CollectionsAdminApp } from '@nuasite/collections-admin'
15
+ import { StrictMode } from 'react'
16
+ import { createRoot } from 'react-dom/client'
17
+
18
+ function readApiBase(): string {
19
+ const value = window.__NUA_ADMIN_API_BASE__
20
+ if (typeof value !== 'string' || value === '') {
21
+ throw new Error('[nua-cms] /_nua/admin: window.__NUA_ADMIN_API_BASE__ is not set')
22
+ }
23
+ return value
24
+ }
25
+
26
+ const container = document.getElementById('nua-admin-root')
27
+ if (!container) {
28
+ throw new Error('[nua-cms] /_nua/admin: #nua-admin-root container is missing')
29
+ }
30
+
31
+ createRoot(container).render(
32
+ <StrictMode>
33
+ <CollectionsAdminApp apiBase={readApiBase()} />
34
+ </StrictMode>,
35
+ )
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Ambient globals for the local `/_nua/admin` SPA entry (cms-headless F7).
3
+ *
4
+ * The dev middleware injects the cms-sidecar `apiBase` into the HTML shell as a
5
+ * window global; the entry reads it to drive `<CollectionsAdminApp apiBase={…} />`.
6
+ */
7
+
8
+ declare global {
9
+ interface Window {
10
+ /** Base URL the in-process cms-sidecar is mounted at (the SPA adds nothing else; it is already the `/cms/v1` base). */
11
+ __NUA_ADMIN_API_BASE__?: string
12
+ }
13
+ }
14
+
15
+ export {}
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../../tsconfig.settings.json",
3
+ "compilerOptions": {
4
+ "composite": false,
5
+ "noEmit": true,
6
+ "emitDeclarationOnly": false,
7
+ "jsx": "react-jsx",
8
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
9
+ "types": ["react", "react-dom"]
10
+ },
11
+ "references": [
12
+ { "path": "../../../collections-admin/src" },
13
+ { "path": "../../../cms-types/src" }
14
+ ]
15
+ }
@@ -0,0 +1 @@
1
+ {"fileNames":["../../../../node_modules/typescript/lib/lib.es5.d.ts","../../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../../node_modules/typescript/lib/lib.es2023.d.ts","../../../../node_modules/typescript/lib/lib.es2024.d.ts","../../../../node_modules/typescript/lib/lib.es2025.d.ts","../../../../node_modules/typescript/lib/lib.esnext.d.ts","../../../../node_modules/typescript/lib/lib.dom.d.ts","../../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","../../../../node_modules/typescript/lib/lib.es2024.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2024.object.d.ts","../../../../node_modules/typescript/lib/lib.es2024.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2024.regexp.d.ts","../../../../node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.es2024.string.d.ts","../../../../node_modules/typescript/lib/lib.es2025.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2025.float16.d.ts","../../../../node_modules/typescript/lib/lib.es2025.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2025.iterator.d.ts","../../../../node_modules/typescript/lib/lib.es2025.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2025.regexp.d.ts","../../../../node_modules/typescript/lib/lib.esnext.array.d.ts","../../../../node_modules/typescript/lib/lib.esnext.collection.d.ts","../../../../node_modules/typescript/lib/lib.esnext.date.d.ts","../../../../node_modules/typescript/lib/lib.esnext.decorators.d.ts","../../../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../../../node_modules/typescript/lib/lib.esnext.error.d.ts","../../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../../node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.esnext.temporal.d.ts","../../../../node_modules/typescript/lib/lib.esnext.typedarrays.d.ts","../../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../../node_modules/@types/react/global.d.ts","../../../../node_modules/csstype/index.d.ts","../../../../node_modules/@types/react/index.d.ts","../../../../node_modules/@types/react/jsx-runtime.d.ts","../../../collections-admin/dist/types/app.d.ts","../../../cms-types/dist/types/index.d.ts","../../../collections-admin/dist/types/client.d.ts","../../../collections-admin/dist/types/form-model.d.ts","../../../collections-admin/dist/types/index.d.ts","../../../../node_modules/@types/react-dom/client.d.ts","./entry.tsx","./env.d.ts","../../../../node_modules/@types/react-dom/index.d.ts"],"fileIdsList":[[92],[90,91],[92,93,98,99],[95],[94,95,96,97]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"1e9332c23e9a907175e0ffc6a49e236f97b48838cc8aec9ce7e4cec21e544b65","impliedFormat":1},{"version":"3753fbc1113dc511214802a2342280a8b284ab9094f6420e7aa171e868679f91","impliedFormat":1},{"version":"999ca32883495a866aa5737fe1babc764a469e4cde6ee6b136a4b9ae68853e4b","impliedFormat":1},{"version":"17f13ecb98cbc39243f2eee1f16d45cd8ec4706b03ee314f1915f1a8b42f6984","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"0bd714129fca875f7d4c477a1a392200b0bcd13fb2e80928cd334b63830ea047","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2c9037ae6cd2c52d80ceef0b3c5ffdb488627d71529cf4f63776daf11161c9a","affectsGlobalScope":true,"impliedFormat":1},{"version":"135d5cf4d345f59f1a9caadfafcd858d3d9cc68290db616cc85797224448cccc","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc238c3f81c2984751932b6aab223cd5b830e0ac6cad76389e5e9d2ffc03287d","affectsGlobalScope":true,"impliedFormat":1},{"version":"4a07f9b76d361f572620927e5735b77d6d2101c23cdd94383eb5b706e7b36357","affectsGlobalScope":true,"impliedFormat":1},{"version":"7c4e8dc6ab834cc6baa0227e030606d29e3e8449a9f67cdf5605ea5493c4db29","affectsGlobalScope":true,"impliedFormat":1},{"version":"de7ba0fd02e06cd9a5bd4ab441ed0e122735786e67dde1e849cced1cd8b46b78","affectsGlobalScope":true,"impliedFormat":1},{"version":"6148e4e88d720a06855071c3db02069434142a8332cf9c182cda551adedf3156","affectsGlobalScope":true,"impliedFormat":1},{"version":"d63dba625b108316a40c95a4425f8d4294e0deeccfd6c7e59d819efa19e23409","affectsGlobalScope":true,"impliedFormat":1},{"version":"0568d6befee03dd435bed4fc25c4e46865b24bdcb8c563fdc21f580a2c301904","affectsGlobalScope":true,"impliedFormat":1},{"version":"30d62269b05b584741f19a5369852d5d34895aa2ac4fd948956f886d15f9cc0d","affectsGlobalScope":true,"impliedFormat":1},{"version":"f128dae7c44d8f35ee42e0a437000a57c9f06cc04f8b4fb42eebf44954d53dc8","affectsGlobalScope":true,"impliedFormat":1},{"version":"ffbe6d7b295306b2ba88030f65b74c107d8d99bdcf596ea99c62a02f606108b0","affectsGlobalScope":true,"impliedFormat":1},{"version":"996fb27b15277369c68a4ba46ed138b4e9e839a02fb4ec756f7997629242fd9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"79b712591b270d4778c89706ca2cfc56ddb8c3f895840e477388f1710dc5eda9","affectsGlobalScope":true,"impliedFormat":1},{"version":"20884846cef428b992b9bd032e70a4ef88e349263f63aeddf04dda837a7dba26","affectsGlobalScope":true,"impliedFormat":1},{"version":"5fcab789c73a97cd43828ee3cc94a61264cf24d4c44472ce64ced0e0f148bdb2","affectsGlobalScope":true,"impliedFormat":1},{"version":"db59a81f070c1880ad645b2c0275022baa6a0c4f0acdc58d29d349c6efcf0903","affectsGlobalScope":true,"impliedFormat":1},{"version":"673294292640f5722b700e7d814e17aaf7d93f83a48a2c9b38f33cbc940ad8b0","affectsGlobalScope":true,"impliedFormat":1},{"version":"d786b48f934cbca483b3c6d0a798cb43bbb4ada283e76fb22c28e53ae05b9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ecb8e347cb6b2a8927c09b86263663289418df375f5e68e11a0ae683776978f","affectsGlobalScope":true,"impliedFormat":1},{"version":"142efd4ce210576f777dc34df121777be89eda476942d6d6663b03dcb53be3ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"379bc41580c2d774f82e828c70308f24a005b490c25ba34d679d84bcf05c3d9d","affectsGlobalScope":true,"impliedFormat":1},{"version":"ed484fb2aa8a1a23d0277056ec3336e0a0b52f9b8d6a961f338a642faf43235d","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ffedae1d1c2d53fdbca1c96d3c7dda544281f7d262f99b6880634f8fd8d9820","affectsGlobalScope":true,"impliedFormat":1},{"version":"83a730b125d477dd264df8ba479afab27a3dae7152b005c214ab94dc7ee44fd3","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e29f41b158de217f94cb9676bf9cbd0cd9b5a46e1985141ed36e075c52bf6ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"2577e7e800bdece2956ca027cb5c17aa359abd968eb9355760110c853f4fb9da","impliedFormat":1},{"version":"b838d4c72740eb0afd284bf7575b74c624b105eff2e8c7b4aeead57e7ac320ff","impliedFormat":1},"af732cf34bfa338fff320258775aa469d8bc3e0f25b5c82e231046ae5dccabf7","c43c2a0107a2a099fe50bcc754e90b50aa6b265ce57e464a2489798b38e4dc53","18be101c2011a0c364fc7e5ee231d6a9397808e9a095b4bb25c171adf4f23ff5","35ac5e9e25a23b55393daa079c3e7b85817598eed090c2b6b92d156fbde16c6b","d1a6a20b9ba01e597090d73d614ea6e39dc0a5424261f6980280f189c05b36b1",{"version":"bc03c3c352f689e38c0ddd50c39b1e65d59273991bfc8858a9e3c0ebb79c023b","impliedFormat":1},"3044ee76859e5dae484bafae0e31525f2a3378d41a3b24c495b2e8e7b690e52c",{"version":"55793e486e9c2ad120621fcba96981896ee79991dbfe795758e6e77e75d0df54","affectsGlobalScope":true},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1}],"root":[100,101],"options":{"allowImportingTsExtensions":true,"allowJs":true,"composite":false,"declaration":true,"declarationMap":true,"emitDeclarationOnly":false,"jsx":4,"module":200,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":false,"noUncheckedIndexedAccess":true,"noUnusedLocals":false,"noUnusedParameters":false,"skipLibCheck":true,"strict":true,"target":99,"verbatimModuleSyntax":true},"referencedMap":[[99,1],[102,1],[92,2],[93,1],[100,3],[94,1],[96,4],[97,4],[98,5]],"affectedFilesPendingEmit":[[100,49]],"version":"6.0.2"}
@@ -22,7 +22,10 @@ const confirmDeleteSlug = signal<string | null>(null)
22
22
  const EMPTY_ENTRIES: never[] = []
23
23
 
24
24
  export function CollectionsBrowser() {
25
- const visible = isCollectionsBrowserOpen.value
25
+ // Collection management (browse/list/open entries) can be owned by the host
26
+ // app; when disabled, the in-preview browser is hidden entirely.
27
+ const collectionManagementEnabled = config.value.features?.collectionManagement !== false
28
+ const visible = collectionManagementEnabled && isCollectionsBrowserOpen.value
26
29
  const selected = selectedBrowserCollection.value
27
30
 
28
31
  const collectionDefinitions = manifest.value.collectionDefinitions ?? {}
@@ -95,6 +95,11 @@ export const Toolbar = ({ callbacks, collectionDefinitions }: ToolbarProps) => {
95
95
  })
96
96
  }
97
97
 
98
+ // When collection management is disabled (e.g. it lives in the host app's
99
+ // Collections tab), hide the in-preview collection browser entry points.
100
+ // Inline editing of the current page's content ("Edit Content") is kept.
101
+ const collectionManagementEnabled = signals.config.value.features?.collectionManagement !== false
102
+
98
103
  if (collectionDefinitions) {
99
104
  const entries = Object.entries(collectionDefinitions)
100
105
  if (entries.length > 0) {
@@ -111,12 +116,14 @@ export const Toolbar = ({ callbacks, collectionDefinitions }: ToolbarProps) => {
111
116
  ordered.push([name, def, false])
112
117
  }
113
118
 
114
- const contentItems: MenuItem[] = ordered.map(([name, def, indented]) => ({
115
- label: def.label,
116
- icon: <GridIcon />,
117
- indented,
118
- onClick: () => callbacks.onOpenCollection?.(name),
119
- }))
119
+ const contentItems: MenuItem[] = collectionManagementEnabled
120
+ ? ordered.map(([name, def, indented]) => ({
121
+ label: def.label,
122
+ icon: <GridIcon />,
123
+ indented,
124
+ onClick: () => callbacks.onOpenCollection?.(name),
125
+ }))
126
+ : []
120
127
 
121
128
  if (currentPageCollection && callbacks.onEditContent) {
122
129
  contentItems.unshift({
@@ -134,11 +141,13 @@ export const Toolbar = ({ callbacks, collectionDefinitions }: ToolbarProps) => {
134
141
  })
135
142
  }
136
143
 
137
- menuSections.push({
138
- label: 'Content',
139
- icon: <GridIcon />,
140
- items: contentItems,
141
- })
144
+ if (contentItems.length > 0) {
145
+ menuSections.push({
146
+ label: 'Content',
147
+ icon: <GridIcon />,
148
+ items: contentItems,
149
+ })
150
+ }
142
151
  }
143
152
  }
144
153
 
@@ -1470,8 +1470,10 @@ export function setConfig(newConfig: CmsConfig): void {
1470
1470
 
1471
1471
  export function setFeatures(features: CmsConfig['features']): void {
1472
1472
  const current = config.value.features
1473
- if (current?.selectElement === features?.selectElement) return
1474
- config.value = { ...config.value, features: { ...current, ...features } }
1473
+ const next = { ...current, ...features }
1474
+ // Bail out when nothing actually changes, to avoid re-triggering effects.
1475
+ if (current?.selectElement === next.selectElement && current?.collectionManagement === next.collectionManagement) return
1476
+ config.value = { ...config.value, features: next }
1475
1477
  }
1476
1478
 
1477
1479
  // ============================================================================
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { AstroIntegration } from 'astro'
2
- import { existsSync, readFileSync } from 'node:fs'
2
+ import { existsSync } from 'node:fs'
3
3
  import fs from 'node:fs/promises'
4
4
  import { dirname, join } from 'node:path'
5
5
  import { fileURLToPath } from 'node:url'
@@ -11,8 +11,10 @@ import { ComponentRegistry } from './component-registry'
11
11
  import { resetProjectRoot } from './config'
12
12
  import { createDevMiddleware } from './dev-middleware'
13
13
  import { getErrorCollector, resetErrorCollector } from './error-collector'
14
+ import { ADMIN_ROUTE, createLocalAdminMiddleware } from './local-admin'
14
15
  import { ManifestWriter } from './manifest-writer'
15
16
  import type { MediaStorageAdapter } from './media/types'
17
+ import { type CmsMode, resolveCmsMode } from './mode'
16
18
  import { rehypeCmsMarker } from './rehype-cms-marker'
17
19
  import type { CmsFeatures, CmsMarkerOptions, ComponentDefinition } from './types'
18
20
  import { createPublicStaticFileChecker } from './utils'
@@ -20,8 +22,18 @@ import { createVitePlugin } from './vite-plugin'
20
22
 
21
23
  export interface NuaCmsOptions extends CmsMarkerOptions {
22
24
  /**
23
- * URL to the CMS editor script.
24
- * If not set, the built-in editor bundle is served from the dev server.
25
+ * URL to the CMS editor (inline visual-editing widget) script.
26
+ *
27
+ * Resolution order in dev:
28
+ * 1. this `src`, if set;
29
+ * 2. the `NUA_CMS_EDITOR_SRC` environment variable (lets the host runtime point
30
+ * dev-preview at a specific CDN/local editor without a config change);
31
+ * 3. the public CDN editor (`DEFAULT_CDN_EDITOR_SRC`) when a pre-built editor
32
+ * bundle ships with the package (the npm-installed case — e.g. a generated
33
+ * site's dev-preview), so the inline editor updates via a CDN push,
34
+ * independent of the site's `@nuasite/cms` version (matching hosting);
35
+ * 4. the bundled editor served from the dev server, used only in the monorepo
36
+ * (no pre-built bundle) so editor source changes hot-reload.
25
37
  */
26
38
  src?: string
27
39
  /**
@@ -44,6 +56,22 @@ export interface NuaCmsOptions extends CmsMarkerOptions {
44
56
  */
45
57
  siteTheme?: 'auto' | 'light' | 'dark'
46
58
  }
59
+ /**
60
+ * Run mode (cms-headless F7). Controls whether the plugin serves a local
61
+ * full-page collections admin:
62
+ *
63
+ * - `local` (default for `pletivo dev` on a developer machine): lazily spawn an
64
+ * in-process cms-sidecar over the project's `node:fs` and serve the
65
+ * `@nuasite/collections-admin` SPA at `/_nua/admin`. The inline widget runs
66
+ * in-page as usual.
67
+ * - `hosted` (inside the agent sandbox): a no-op for spawning/serving — the
68
+ * sidecar is a managed sandbox service and the admin is the webmaster tab.
69
+ * The plugin stays marker + CDN-inject only.
70
+ *
71
+ * Auto-detected from the environment when omitted (a sandbox env signal ⇒
72
+ * `hosted`; otherwise `local`). An explicit value always wins.
73
+ */
74
+ mode?: CmsMode
47
75
  /**
48
76
  * Proxy /_nua/cms requests to this target URL during dev.
49
77
  * Example: 'http://localhost:8787'
@@ -88,6 +116,20 @@ const DEFAULT_MAX_UPLOAD_SIZE = 10 * 1024 * 1024
88
116
 
89
117
  const VIRTUAL_CMS_PATH = '/@nuasite/cms-editor.js'
90
118
 
119
+ /**
120
+ * Virtual module id of the local `/_nua/admin` SPA entry (cms-headless F7). The
121
+ * HTML shell loads it as `<script type="module">`; the Vite plugin resolves it to
122
+ * `src/admin/entry.tsx` so the dev server transforms it (TSX → JS, real React).
123
+ */
124
+ const VIRTUAL_ADMIN_ENTRY = '/@nuasite/cms-admin-entry.js'
125
+
126
+ /**
127
+ * Public CDN editor script. Same URL hosting injects (see webmaster
128
+ * `packages/worker-hosting` `editorSrc`), so dev-preview and hosting load the
129
+ * identical inline editor and a CDN push updates both without touching the site.
130
+ */
131
+ const DEFAULT_CDN_EDITOR_SRC = 'https://cdn.nuasite.com/script/latest/cms-editor.js'
132
+
91
133
  export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
92
134
  const {
93
135
  // CMS editor options
@@ -111,6 +153,13 @@ export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
111
153
  maxUploadSize = DEFAULT_MAX_UPLOAD_SIZE,
112
154
  } = options
113
155
 
156
+ // Run mode (cms-headless F7): `local` serves a full-page collections admin at
157
+ // /_nua/admin over an in-process sidecar; `hosted` (inside the agent sandbox)
158
+ // is a no-op for that — the managed sandbox sidecar + the webmaster tab own it.
159
+ // An explicit `options.mode` wins; otherwise auto-detect from the environment.
160
+ const mode = resolveCmsMode(options.mode)
161
+ const serveLocalAdmin = mode === 'local'
162
+
114
163
  // When no proxy, enable local CMS API with default media adapter
115
164
  const enableCmsApi = !proxy
116
165
  const mediaAdapter = media ?? (enableCmsApi ? createLocalStorageAdapter() : undefined)
@@ -218,15 +267,41 @@ export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
218
267
  }
219
268
 
220
269
  const vitePlugins: any[] = [...(createVitePlugin(pluginContext) as any)]
221
- const cmsDir = !src ? dirname(fileURLToPath(import.meta.url)) : undefined
270
+ const cmsDir = dirname(fileURLToPath(import.meta.url))
271
+
272
+ // Local-mode (cms-headless F7): resolve the /_nua/admin SPA entry virtual
273
+ // module to src/admin/entry.tsx so Vite transforms it (TSX → JS, real
274
+ // React) and HMR works. The HTML shell loads this id as a module script.
275
+ if (serveLocalAdmin) {
276
+ vitePlugins.push({
277
+ name: 'nuasite-cms-admin-entry',
278
+ resolveId(id: string) {
279
+ if (id === VIRTUAL_ADMIN_ENTRY) {
280
+ return join(cmsDir, 'admin/entry.tsx')
281
+ }
282
+ },
283
+ })
284
+ }
222
285
 
223
286
  // Detect pre-built editor bundle (present when installed from npm)
224
- const editorBundlePath = cmsDir ? join(cmsDir, '../dist/editor.js') : undefined
225
- const hasPrebuiltBundle = editorBundlePath ? existsSync(editorBundlePath) : false
287
+ const editorBundlePath = join(cmsDir, '../dist/editor.js')
288
+ const hasPrebuiltBundle = existsSync(editorBundlePath)
289
+
290
+ // Resolve which editor script dev-preview injects:
291
+ // 1. explicit `src`; 2. `NUA_CMS_EDITOR_SRC` env; 3. the public CDN editor
292
+ // when shipping a pre-built bundle (npm-installed site) — so dev-preview
293
+ // loads the same CDN editor as hosting and a CDN push updates it without a
294
+ // site rebuild; 4. the bundled source (monorepo only) for editor HMR.
295
+ const envSrc = process.env.NUA_CMS_EDITOR_SRC
296
+ const resolvedEditorSrc = src ?? envSrc ?? (hasPrebuiltBundle ? DEFAULT_CDN_EDITOR_SRC : VIRTUAL_CMS_PATH)
297
+
298
+ // Local virtual-module serving is only needed when injecting the bundled
299
+ // editor (the monorepo source path) — not for an external/CDN URL.
300
+ const servesBundledEditor = resolvedEditorSrc === VIRTUAL_CMS_PATH
226
301
 
227
302
  // --- CMS Editor setup (dev only) ---
228
303
  if (command === 'dev') {
229
- const editorSrc = src ?? VIRTUAL_CMS_PATH
304
+ const editorSrc = resolvedEditorSrc
230
305
 
231
306
  const configScript = `window.NuaCmsConfig = ${JSON.stringify(resolvedCmsConfig)};`
232
307
 
@@ -248,52 +323,32 @@ export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
248
323
  `,
249
324
  )
250
325
 
251
- if (!src) {
252
- if (hasPrebuiltBundle) {
253
- // Pre-built bundle exists (npm install case):
254
- // Serve it via a virtual module — no JSX pragma, Tailwind, or aliases needed.
255
- // Read on every load() so rebuilds during dev pick up without restarting
256
- // the host (Astro, pletivo, etc).
257
- vitePlugins.push({
258
- name: 'nuasite-cms-editor',
259
- resolveId(id: string) {
260
- if (id === VIRTUAL_CMS_PATH) {
261
- return VIRTUAL_CMS_PATH
262
- }
263
- },
264
- load(id: string) {
265
- if (id === VIRTUAL_CMS_PATH) {
266
- return readFileSync(editorBundlePath!, 'utf-8')
267
- }
268
- },
269
- })
270
- } else {
271
- // No pre-built bundle (monorepo dev case):
272
- // Serve source files directly — Vite transforms TSX, resolves imports, HMR works.
273
- vitePlugins.push({
274
- name: 'nuasite-cms-editor',
275
- resolveId(id: string) {
276
- if (id === VIRTUAL_CMS_PATH) {
277
- return join(cmsDir!, 'editor/index.tsx')
278
- }
279
- },
280
- })
281
-
282
- // Prepend @jsxImportSource pragma for editor .tsx files
283
- // so Vite's esbuild uses Preact's h function
284
- vitePlugins.push({
285
- name: 'nuasite-cms-preact-jsx',
286
- transform(code: string, id: string) {
287
- if (id.includes('/src/editor/') && id.endsWith('.tsx') && !code.includes('@jsxImportSource')) {
288
- return `/** @jsxImportSource preact */\n${code}`
289
- }
290
- },
291
- })
292
-
293
- // Add Tailwind CSS Vite plugin for editor styles
294
- const tailwindcss = (await import('@tailwindcss/vite')).default
295
- vitePlugins.push(tailwindcss())
296
- }
326
+ if (servesBundledEditor) {
327
+ // Monorepo dev (no pre-built bundle): serve the editor source files
328
+ // directly so Vite transforms TSX, resolves imports, and HMR works.
329
+ vitePlugins.push({
330
+ name: 'nuasite-cms-editor',
331
+ resolveId(id: string) {
332
+ if (id === VIRTUAL_CMS_PATH) {
333
+ return join(cmsDir, 'editor/index.tsx')
334
+ }
335
+ },
336
+ })
337
+
338
+ // Prepend @jsxImportSource pragma for editor .tsx files
339
+ // so Vite's esbuild uses Preact's h function
340
+ vitePlugins.push({
341
+ name: 'nuasite-cms-preact-jsx',
342
+ transform(code: string, id: string) {
343
+ if (id.includes('/src/editor/') && id.endsWith('.tsx') && !code.includes('@jsxImportSource')) {
344
+ return `/** @jsxImportSource preact */\n${code}`
345
+ }
346
+ },
347
+ })
348
+
349
+ // Add Tailwind CSS Vite plugin for editor styles
350
+ const tailwindcss = (await import('@tailwindcss/vite')).default
351
+ vitePlugins.push(tailwindcss())
297
352
  }
298
353
  }
299
354
 
@@ -306,8 +361,9 @@ export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
306
361
  }
307
362
  }
308
363
 
309
- // Only add react->preact aliases when serving source files (not pre-built bundle)
310
- const needsAliases = !src && !hasPrebuiltBundle
364
+ // Only add react->preact aliases when serving the editor source files
365
+ // (monorepo dev) an external/CDN editor URL needs no module rewriting.
366
+ const needsAliases = servesBundledEditor
311
367
 
312
368
  updateConfig({
313
369
  markdown: {
@@ -349,6 +405,22 @@ export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
349
405
  if (enableCmsApi) {
350
406
  logger.info('CMS API enabled at /_nua/cms/')
351
407
  }
408
+
409
+ // Local-mode full-page collections admin (cms-headless F7). Registered
410
+ // only in `local` mode — in `hosted` (sandbox) this is a strict no-op:
411
+ // the managed sandbox sidecar (F2) + the webmaster tab (F3) own it.
412
+ // The in-process sidecar + SPA are built lazily on the first /_nua/admin
413
+ // hit, so dev startup stays fast. Media defaults to local public/uploads.
414
+ if (serveLocalAdmin) {
415
+ createLocalAdminMiddleware(server, {
416
+ contentDir,
417
+ componentDirs,
418
+ mediaAdapter: media ?? createLocalStorageAdapter(),
419
+ maxUploadSize,
420
+ entryModuleId: VIRTUAL_ADMIN_ENTRY,
421
+ })
422
+ logger.info(`CMS collections admin available at ${ADMIN_ROUTE}`)
423
+ }
352
424
  },
353
425
 
354
426
  'astro:build:done': async ({ dir, logger }) => {
@@ -402,6 +474,7 @@ export { FIELD_TYPES, isFieldType } from '@nuasite/cms-types'
402
474
  export { n } from './field-types'
403
475
  export type { DateHints, ImageHints, NumberHints, TextareaHints, TextHints } from './field-types'
404
476
  export type { MediaFolderItem, MediaItem, MediaListOptions, MediaListResult, MediaStorageAdapter, MediaTypeFilter } from './media/types'
477
+ export { type CmsMode, detectHostedFromEnv, resolveCmsMode } from './mode'
405
478
  export type { Color, Date, DateTime, Email, Image, Reference, Textarea, Time, Url } from './prop-types'
406
479
 
407
480
  export { scanCollections } from './collection-scanner'