@morphemecms/cms 0.1.1-next-20261103223426 → 0.2.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 (70) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/bin/morpheme.mjs +1 -1
  3. package/lib/apps.mjs +5 -2
  4. package/lib/apps.test.d.mts +1 -0
  5. package/lib/apps.test.mjs +50 -0
  6. package/lib/caseCollisions.d.mts +4 -0
  7. package/lib/caseCollisions.mjs +62 -0
  8. package/lib/caseCollisions.test.d.mts +1 -0
  9. package/lib/caseCollisions.test.mjs +74 -0
  10. package/lib/contracts.d.mts +15 -0
  11. package/lib/contracts.mjs +17 -0
  12. package/lib/licenses.d.mts +1 -1
  13. package/lib/licenses.mjs +2 -2
  14. package/lib/storeEntries.d.mts +18 -0
  15. package/lib/storeEntries.mjs +64 -0
  16. package/lib/storeEntries.test.d.mts +1 -0
  17. package/lib/storeEntries.test.mjs +71 -0
  18. package/package.json +1 -1
  19. package/pages/editor/sw.js +1 -1
  20. package/scripts/built-site.mjs +37 -2
  21. package/scripts/check-content.mjs +4 -2
  22. package/scripts/check-store.mjs +160 -0
  23. package/site/defineSite.d.mts +2 -14
  24. package/site/defineSite.mjs +2 -7
  25. package/site/storeTheme.d.mts +6 -0
  26. package/site/storeTheme.mjs +29 -0
  27. package/site/storeTheme.test.d.mts +1 -0
  28. package/site/storeTheme.test.mjs +53 -0
  29. package/site/theme.mjs +14 -3
  30. package/src/App.tsx +13 -16
  31. package/src/AppList.tsx +22 -5
  32. package/src/Consents.tsx +2 -2
  33. package/src/Deleted.tsx +1 -1
  34. package/src/EntryForm.tsx +3 -3
  35. package/src/FormFrame.tsx +3 -3
  36. package/src/Library.tsx +2 -2
  37. package/src/Licenses.tsx +1 -1
  38. package/src/Media.tsx +2 -2
  39. package/src/Notifications.tsx +2 -2
  40. package/src/Redirects.tsx +2 -2
  41. package/src/Screen.tsx +1 -1
  42. package/src/ThemeStore.tsx +1 -1
  43. package/src/apps.ts +2 -2
  44. package/src/checkSite.ts +2 -2
  45. package/src/deploy.ts +1 -1
  46. package/src/i18n/da-DK/consents.ts +1 -1
  47. package/src/i18n/en-US/apps.ts +1 -1
  48. package/src/i18n/en-US/consents.ts +1 -1
  49. package/src/i18n/en-US/library.ts +1 -1
  50. package/src/i18n/en-US/licenses.ts +1 -1
  51. package/src/i18n/en-US/redirects.ts +2 -2
  52. package/src/store.ts +74 -94
  53. package/src/themes.ts +1 -1
  54. package/starter/README.md +1 -0
  55. package/theme/styles/ui.css +4 -4
  56. package/theme/ui/BottomSheet.tsx +3 -3
  57. package/theme/ui/Dialog.tsx +1 -1
  58. package/theme/ui/SideSheet.tsx +1 -1
  59. package/theme/ui/bottomSheet.script.ts +2 -2
  60. package/worker/consent.js +1 -1
  61. package/worker/index.js +4 -0
  62. package/worker/push.js +1 -1
  63. package/worker/store.js +46 -0
  64. /package/src/{consents.ts → consentData.ts} +0 -0
  65. /package/src/{licenses.ts → licenseData.ts} +0 -0
  66. /package/src/{notifications.ts → notificationData.ts} +0 -0
  67. /package/src/{redirects.ts → redirectData.ts} +0 -0
  68. /package/theme/ui/{bottomSheet.ts → bottomSheetControl.ts} +0 -0
  69. /package/theme/ui/{dialog.ts → dialogControl.ts} +0 -0
  70. /package/theme/ui/{sideSheet.ts → sideSheetControl.ts} +0 -0
package/worker/push.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // The editor's notifications on the phone or computer also when the editor is closed: Web Push from the Worker
2
- // (packages/editor/src/notifications.ts, packages/editor/pages/editor/sw.js). A device where "På telefonen" is on under "Konto" ›
2
+ // (packages/editor/src/notificationData.ts, packages/editor/pages/editor/sw.js). A device where "På telefonen" is on under "Konto" ›
3
3
  // "Notifikationer" signs up here with the browser's push subscription, the types it has turned off and the editor's
4
4
  // language; the Worker sends to the browser's push service (Google's, Mozilla's, Apple's), which wakes the editor's
5
5
  // service worker, which shows it. Kept in Workers KV (the binding PUSH in wrangler.jsonc):
@@ -0,0 +1,46 @@
1
+ // What the editor asks of the store, through the Worker (the store's key never leaves it): the catalog and the files in it.
2
+ // Exposes handleStore(request, env, ctx, ask) and STORE_URL; used by packages/editor/worker/index.js (/api/store/*).
3
+ // Depends on packages/editor/worker/session.js (sign-in and access) and packages/editor/lib/contracts.mjs (APP_API, THEME_API).
4
+ // GET /api/store/catalog the store's catalog for this site's contracts; { connected: false } without MORPHEME_STORE_KEY
5
+ // GET /api/store/files/<oid> a file of the store by its git id, streamed through with its content-type and cache-control
6
+ import { APP_API, THEME_API } from '../lib/contracts.mjs';
7
+ import { access, sessionToken } from './session.js';
8
+ import { json } from './not-found.js';
9
+
10
+ export const STORE_URL = 'https://morpheme-appstore.larsadolfsen.workers.dev';
11
+
12
+ const OID = /^[0-9a-f]{40}$/;
13
+
14
+ /** @param {Request} request @param {Record<string, any>} env @param {unknown} _ctx @param {typeof fetch} [ask] fetch, for the store and GitHub */
15
+ export async function handleStore(request, env, _ctx, ask = fetch) {
16
+ if (!sessionToken(request)) return json({ error: 'signed out' }, 401);
17
+ const may = await access(request, ask);
18
+ if (!may) return json({ error: 'signed out' }, 401);
19
+ if (!may.read) return json({ error: 'forbidden' }, 403);
20
+ if (request.method !== 'GET') return json({ error: 'method' }, 405);
21
+ const route = new URL(request.url).pathname.slice('/api/store/'.length);
22
+ const isCatalog = route === 'catalog';
23
+ const oid = route.startsWith('files/') ? route.slice('files/'.length) : null;
24
+ if (!isCatalog && !(oid !== null && OID.test(oid))) return json({ error: 'not found' }, 404);
25
+ if (!env.MORPHEME_STORE_KEY) return isCatalog ? json({ connected: false }) : json({ error: 'not found' }, 404);
26
+
27
+ const base = env.MORPHEME_STORE_URL ?? STORE_URL;
28
+ const url = isCatalog ? `${base}/store/catalog?app=${APP_API}&theme=${THEME_API}` : `${base}/store/files/${oid}`;
29
+ let res;
30
+ try {
31
+ res = await ask(url, { headers: { authorization: `Bearer ${env.MORPHEME_STORE_KEY}` } });
32
+ } catch {
33
+ return json({ error: 'store failed' }, 502);
34
+ }
35
+ if (res.status === 401 || res.status === 403) return json({ error: 'store refused' }, 502);
36
+ if (!isCatalog && res.status === 404) return json({ error: 'not found' }, 404);
37
+ if (res.status !== 200) return json({ error: 'store failed' }, 502);
38
+ if (isCatalog) {
39
+ const catalog = await res.json().catch(() => null);
40
+ return catalog === null ? json({ error: 'store failed' }, 502) : json(catalog);
41
+ }
42
+ const headers = { 'content-type': res.headers.get('content-type') ?? 'application/octet-stream' };
43
+ const cache = res.headers.get('cache-control');
44
+ if (cache) headers['cache-control'] = cache;
45
+ return new Response(res.body, { status: 200, headers });
46
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes