alinea 2.0.0-preview.3 → 2.0.0-preview.4

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 (154) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/LICENSES.md +144 -90
  3. package/dist/adapter/next/DevRemote.js +10 -2
  4. package/dist/adapter/next/previews.js +1 -0
  5. package/dist/backend/Handler.js +14 -7
  6. package/dist/backend/api/BasicAuth.d.ts +1 -1
  7. package/dist/backend/api/BasicAuth.js +14 -14
  8. package/dist/backend/api/OAuth2.d.ts +3 -3
  9. package/dist/backend/api/OAuth2.js +7 -4
  10. package/dist/bundled.d.ts +96 -25
  11. package/dist/chunks/{chunk-Y7XOMJOC.js → chunk-CFNRVI3Y.js} +220 -247
  12. package/dist/chunks/chunk-D6UJHBJJ.js +183 -0
  13. package/dist/chunks/chunk-TIJTT5ZI.js +228 -0
  14. package/dist/chunks/{chunk-HFBZMKIN.js → chunk-XMOVGDFI.js} +1 -1
  15. package/dist/cli/Serve.js +1 -1
  16. package/dist/cli/bin.js +1 -1
  17. package/dist/cli/serve/LocalAuth.js +1 -1
  18. package/dist/cloud/AuthResult.d.ts +2 -0
  19. package/dist/cloud/CloudHandshake.d.ts +7 -0
  20. package/dist/cloud/CloudHandshake.js +64 -0
  21. package/dist/cloud/CloudRemote.d.ts +4 -1
  22. package/dist/cloud/CloudRemote.js +21 -3
  23. package/dist/components/Calendar.js +6 -6
  24. package/dist/components/Checkbox.js +2 -2
  25. package/dist/components/ComboBox.js +12 -12
  26. package/dist/components/DatePicker.js +4 -4
  27. package/dist/components/DateRangePicker.js +4 -4
  28. package/dist/components/Disclosure.js +6 -6
  29. package/dist/components/Label.js +6 -6
  30. package/dist/components/List.js +37 -37
  31. package/dist/components/Menu.js +4 -4
  32. package/dist/components/Modal.js +2 -2
  33. package/dist/components/MultipleSelect.js +23 -23
  34. package/dist/components/NumberField.js +5 -5
  35. package/dist/components/ProgressCircle.js +4 -4
  36. package/dist/components/SearchField.js +7 -7
  37. package/dist/components/Select.js +6 -6
  38. package/dist/components/Surface.js +1 -1
  39. package/dist/components/Table.js +8 -8
  40. package/dist/components/TextField.js +4 -4
  41. package/dist/components/TimeField.js +4 -4
  42. package/dist/components/Toggle.d.ts +1 -1
  43. package/dist/components/Toggle.js +2 -2
  44. package/dist/components/Toolbar.js +3 -3
  45. package/dist/components/Tooltip.js +2 -2
  46. package/dist/components/Tree.js +6 -6
  47. package/dist/core/Connection.d.ts +7 -4
  48. package/dist/core/Entry.d.ts +6 -0
  49. package/dist/core/Entry.js +10 -0
  50. package/dist/core/Id.d.ts +1 -0
  51. package/dist/core/Id.js +8 -0
  52. package/dist/core/db/Operation.js +4 -3
  53. package/dist/dashboard/App.js +30 -16
  54. package/dist/dashboard/StoryProvider.js +2 -2
  55. package/dist/dashboard/app/AccessDenied.js +3 -3
  56. package/dist/dashboard/app/ActivityStatus.js +23 -23
  57. package/dist/dashboard/app/AppShell.js +2 -2
  58. package/dist/dashboard/app/AppearanceToggle.d.ts +1 -0
  59. package/dist/dashboard/app/AppearanceToggle.js +43 -0
  60. package/dist/dashboard/app/AuthView.d.ts +1 -1
  61. package/dist/dashboard/app/AuthView.js +17 -19
  62. package/dist/dashboard/app/Badge.js +2 -2
  63. package/dist/dashboard/app/CompactField.js +17 -17
  64. package/dist/dashboard/app/DashboardErrorBoundary.js +23 -11
  65. package/dist/dashboard/app/DashboardLayout.js +15 -8
  66. package/dist/dashboard/app/DashboardMeta.d.ts +2 -1
  67. package/dist/dashboard/app/DashboardMeta.js +20 -5
  68. package/dist/dashboard/app/EntryFields.js +6 -6
  69. package/dist/dashboard/app/EntryHeader.js +27 -27
  70. package/dist/dashboard/app/EntryReferences.js +15 -15
  71. package/dist/dashboard/app/EntrySidebar.js +24 -24
  72. package/dist/dashboard/app/EntrySidebarPreview.js +20 -19
  73. package/dist/dashboard/app/EntryTranslationBanner.js +5 -5
  74. package/dist/dashboard/app/Explorer.js +64 -64
  75. package/dist/dashboard/app/ExplorerCards.js +46 -46
  76. package/dist/dashboard/app/ExplorerFileCard.js +19 -19
  77. package/dist/dashboard/app/ExplorerList.js +20 -20
  78. package/dist/dashboard/app/ExplorerModal.js +5 -5
  79. package/dist/dashboard/app/ExplorerPickerContent.js +2 -2
  80. package/dist/dashboard/app/ExplorerTable.js +63 -63
  81. package/dist/dashboard/app/ImagePicker.js +7 -7
  82. package/dist/dashboard/app/LinkPicker.js +17 -22
  83. package/dist/dashboard/app/LocaleMenu.js +10 -12
  84. package/dist/dashboard/app/SidebarLayout.js +4 -4
  85. package/dist/dashboard/app/SidebarTree.js +58 -58
  86. package/dist/dashboard/app/WorkspaceMenu.d.ts +10 -3
  87. package/dist/dashboard/app/WorkspaceMenu.js +88 -67
  88. package/dist/dashboard/app/WorkspaceMenu.stories.d.ts +2 -0
  89. package/dist/dashboard/app/WorkspaceRoots.d.ts +3 -1
  90. package/dist/dashboard/app/WorkspaceRoots.js +86 -111
  91. package/dist/dashboard/app/editor/FileEditor.js +29 -29
  92. package/dist/dashboard/app/editor/FilePreview.js +6 -6
  93. package/dist/dashboard/app/editor/MediaAltField.view.js +4 -4
  94. package/dist/dashboard/app/modals/CreateEntry.js +15 -15
  95. package/dist/dashboard/app/pages/EntryPage.js +29 -31
  96. package/dist/dashboard/app/pages/RootPage.js +4 -4
  97. package/dist/dashboard/app/pages/SplashPage.d.ts +3 -0
  98. package/dist/dashboard/app/pages/SplashPage.js +414 -0
  99. package/dist/dashboard/app/pages/UsersPage.js +42 -42
  100. package/dist/dashboard/app/ui/DashboardModal.js +16 -16
  101. package/dist/dashboard/app/ui/Rail.js +3 -3
  102. package/dist/dashboard/app/ui/Sidebar.js +2 -2
  103. package/dist/dashboard/atoms/ReactiveNode.js +1 -1
  104. package/dist/dashboard/atoms/activity.js +2 -3
  105. package/dist/dashboard/atoms/auth.d.ts +2 -0
  106. package/dist/dashboard/atoms/auth.js +6 -2
  107. package/dist/dashboard/atoms/config.js +1 -1
  108. package/dist/dashboard/atoms/core.js +2 -2
  109. package/dist/dashboard/atoms/create.js +1 -1
  110. package/dist/dashboard/atoms/dashboard.js +2 -2
  111. package/dist/dashboard/atoms/editor.js +1 -1
  112. package/dist/dashboard/atoms/entry.js +2 -2
  113. package/dist/dashboard/atoms/explorer.d.ts +1 -3
  114. package/dist/dashboard/atoms/explorer.js +7 -9
  115. package/dist/dashboard/atoms/graph.d.ts +1 -0
  116. package/dist/dashboard/atoms/graph.js +7 -2
  117. package/dist/dashboard/atoms/link.js +2 -2
  118. package/dist/dashboard/atoms/nav.d.ts +4 -3
  119. package/dist/dashboard/atoms/nav.js +10 -5
  120. package/dist/dashboard/atoms/preview.js +1 -1
  121. package/dist/dashboard/atoms/root.js +2 -2
  122. package/dist/dashboard/atoms/upload.js +1 -1
  123. package/dist/dashboard/atoms/user.d.ts +1 -1
  124. package/dist/dashboard/atoms/user.js +8 -6
  125. package/dist/dashboard/atoms/utils.js +2 -2
  126. package/dist/dashboard/boot/Boot.js +2 -4
  127. package/dist/dashboard/boot/DashboardWorker.js +34 -29
  128. package/dist/dashboard/editor/UseField.js +6 -6
  129. package/dist/dashboard/fixture/cms.d.ts +12 -0
  130. package/dist/dashboard/fixture/cms.js +53 -2
  131. package/dist/dashboard/hook/UseGraph.js +4 -4
  132. package/dist/dashboard/hook/UseRoot.js +4 -4
  133. package/dist/dashboard/hooks.js +16 -16
  134. package/dist/field/code/CodeField.view.js +12 -12
  135. package/dist/field/link/LinkField.view.js +56 -56
  136. package/dist/field/list/ListField.view.js +24 -24
  137. package/dist/field/localiser/LocalisedField.view.js +76 -5
  138. package/dist/field/metadata/MetadataField.view.js +19 -19
  139. package/dist/field/richtext/PickTextLink.js +6 -6
  140. package/dist/field/richtext/RichTextBlock.js +4 -4
  141. package/dist/field/richtext/RichTextBlocks.js +1 -1
  142. package/dist/field/richtext/RichTextExtensions.js +19 -19
  143. package/dist/field/richtext/RichTextField.view.js +6 -6
  144. package/dist/field/richtext/RichTextInsertMenu.js +3 -3
  145. package/dist/field/richtext/RichTextState.js +1 -1
  146. package/dist/field/text/TextField.view.js +2 -2
  147. package/dist/index.css +415 -28
  148. package/dist/preview/RegisterPreview.d.ts +1 -1
  149. package/dist/preview/RegisterPreview.js +4 -6
  150. package/dist/preview/react.d.ts +5 -1
  151. package/dist/preview/react.js +12 -9
  152. package/package.json +1 -1
  153. package/dist/chunks/chunk-STAJCW4Z.js +0 -322
  154. package/dist/chunks/chunk-U4VOHNR2.js +0 -210
@@ -0,0 +1,183 @@
1
+ import {
2
+ KEY_registerAbortHandler,
3
+ createStore,
4
+ getBuildingBlocks,
5
+ getDefaultStore
6
+ } from "./chunk-CFNRVI3Y.js";
7
+
8
+ // node_modules/jotai/dist/react/Provider.js
9
+ import { createContext, createElement, useContext, useRef } from "react";
10
+ var StoreContext = createContext(void 0);
11
+ function useStore(options) {
12
+ const store = useContext(StoreContext);
13
+ return options?.store || store || getDefaultStore();
14
+ }
15
+ function Provider({ children, store }) {
16
+ const storeRef = useRef(null);
17
+ if (store) {
18
+ return createElement(StoreContext.Provider, { value: store }, children);
19
+ }
20
+ if (storeRef.current === null) {
21
+ storeRef.current = createStore();
22
+ }
23
+ return createElement(StoreContext.Provider, {
24
+ // TODO: If this is not a false positive, consider using useState instead of useRef like https://github.com/pmndrs/jotai/pull/2771
25
+ // eslint-disable-next-line react-hooks/refs
26
+ value: storeRef.current
27
+ }, children);
28
+ }
29
+
30
+ // node_modules/jotai/dist/react/useAtomValueRaw.js
31
+ import { useDebugValue, useEffect, useReducer } from "react";
32
+
33
+ // node_modules/jotai/dist/react/continuablePromise.js
34
+ var isPromiseLike = (x) => typeof x?.then === "function";
35
+ var continuablePromiseMap = /* @__PURE__ */ new WeakMap();
36
+ var createContinuablePromise = (store, promise, getValue) => {
37
+ const buildingBlocks = getBuildingBlocks(store);
38
+ const registerAbortHandler = buildingBlocks[KEY_registerAbortHandler];
39
+ let continuablePromise = continuablePromiseMap.get(promise);
40
+ if (!continuablePromise) {
41
+ continuablePromise = new Promise((resolve, reject) => {
42
+ let curr = promise;
43
+ const onFulfilled = (me) => (v) => {
44
+ if (curr === me) {
45
+ resolve(v);
46
+ }
47
+ };
48
+ const onRejected = (me) => (e) => {
49
+ if (curr === me) {
50
+ reject(e);
51
+ }
52
+ };
53
+ const onAbort = () => {
54
+ try {
55
+ const nextValue = getValue();
56
+ if (isPromiseLike(nextValue)) {
57
+ continuablePromiseMap.set(nextValue, continuablePromise);
58
+ curr = nextValue;
59
+ nextValue.then(onFulfilled(nextValue), onRejected(nextValue));
60
+ registerAbortHandler(buildingBlocks, store, nextValue, onAbort);
61
+ } else {
62
+ resolve(nextValue);
63
+ }
64
+ } catch (e) {
65
+ reject(e);
66
+ }
67
+ };
68
+ promise.then(onFulfilled(promise), onRejected(promise));
69
+ registerAbortHandler(buildingBlocks, store, promise, onAbort);
70
+ });
71
+ continuablePromiseMap.set(promise, continuablePromise);
72
+ }
73
+ return continuablePromise;
74
+ };
75
+
76
+ // node_modules/jotai/dist/react/useAtomValueRaw.js
77
+ function useAtomValueRaw(atom, options) {
78
+ const store = useStore(options);
79
+ const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = useReducer((prev) => {
80
+ const nextValue = store.get(atom);
81
+ if (Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom) {
82
+ return prev;
83
+ }
84
+ return [nextValue, store, atom];
85
+ }, void 0, () => [store.get(atom), store, atom]);
86
+ let value = valueFromReducer;
87
+ if (storeFromReducer !== store || atomFromReducer !== atom) {
88
+ rerender();
89
+ value = store.get(atom);
90
+ }
91
+ useEffect(() => store.sub(atom, rerender), [store, atom]);
92
+ useDebugValue(value);
93
+ if (isPromiseLike(value)) {
94
+ return createContinuablePromise(store, value, () => store.get(atom));
95
+ }
96
+ return value;
97
+ }
98
+
99
+ // node_modules/jotai/dist/react/useAtomValueRawSync.js
100
+ import { useCallback, useDebugValue as useDebugValue2, useSyncExternalStore } from "react";
101
+ function useAtomValueRawSync(atom, options) {
102
+ const store = useStore(options);
103
+ const getSnapshot = useCallback(() => {
104
+ const value2 = store.get(atom);
105
+ if (isPromiseLike(value2)) {
106
+ return createContinuablePromise(store, value2, () => store.get(atom));
107
+ }
108
+ return value2;
109
+ }, [store, atom]);
110
+ const value = useSyncExternalStore(useCallback((callback) => store.sub(atom, callback), [store, atom]), getSnapshot, getSnapshot);
111
+ useDebugValue2(value);
112
+ return value;
113
+ }
114
+
115
+ // node_modules/jotai/dist/react/useSetAtom.js
116
+ import { useCallback as useCallback2 } from "react";
117
+ function useSetAtom(atom, options) {
118
+ const store = useStore(options);
119
+ const setAtom = useCallback2((...args) => {
120
+ if (process.env.NODE_ENV !== "production" && !("write" in atom)) {
121
+ throw new Error("not writable atom");
122
+ }
123
+ return store.set(atom, ...args);
124
+ }, [store, atom]);
125
+ return setAtom;
126
+ }
127
+
128
+ // node_modules/jotai/dist/react/useAtomValue.js
129
+ import React from "react";
130
+ var attachPromiseStatus = (promise) => {
131
+ if (!promise.status) {
132
+ promise.status = "pending";
133
+ promise.then((v) => {
134
+ promise.status = "fulfilled";
135
+ promise.value = v;
136
+ }, (e) => {
137
+ promise.status = "rejected";
138
+ promise.reason = e;
139
+ });
140
+ }
141
+ };
142
+ var use = React.use || // A shim for older React versions
143
+ ((promise) => {
144
+ if (promise.status === "pending") {
145
+ throw promise;
146
+ } else if (promise.status === "fulfilled") {
147
+ return promise.value;
148
+ } else if (promise.status === "rejected") {
149
+ throw promise.reason;
150
+ } else {
151
+ attachPromiseStatus(promise);
152
+ throw promise;
153
+ }
154
+ });
155
+ function useAtomValue(atom, options) {
156
+ const { unstable_promiseStatus: promiseStatus = !React.use } = options || {};
157
+ const value = useAtomValueRaw(atom, options);
158
+ if (isPromiseLike(value)) {
159
+ if (promiseStatus) {
160
+ attachPromiseStatus(value);
161
+ }
162
+ return use(value);
163
+ }
164
+ return value;
165
+ }
166
+
167
+ // node_modules/jotai/dist/react/useAtom.js
168
+ function useAtom(atom, options) {
169
+ return [
170
+ useAtomValue(atom, options),
171
+ // We do wrong type assertion here, which results in throwing an error.
172
+ useSetAtom(atom, options)
173
+ ];
174
+ }
175
+
176
+ export {
177
+ useStore,
178
+ Provider,
179
+ useAtomValueRaw,
180
+ useAtomValueRawSync,
181
+ useSetAtom,
182
+ useAtom
183
+ };
@@ -0,0 +1,228 @@
1
+ import {
2
+ atom
3
+ } from "./chunk-CFNRVI3Y.js";
4
+
5
+ // node_modules/jotai/dist/vanilla/utils/selectAtom.js
6
+ var getCached = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
7
+ var cache1 = /* @__PURE__ */ new WeakMap();
8
+ var memo3 = (create, dep1, dep2, dep3) => {
9
+ const cache2 = getCached(() => /* @__PURE__ */ new WeakMap(), cache1, dep1);
10
+ const cache3 = getCached(() => /* @__PURE__ */ new WeakMap(), cache2, dep2);
11
+ return getCached(create, cache3, dep3);
12
+ };
13
+ function selectAtom(anAtom, selector, equalityFn = Object.is) {
14
+ return memo3(() => {
15
+ const EMPTY = /* @__PURE__ */ Symbol();
16
+ const selectValue = ([value, prevSlice]) => {
17
+ if (prevSlice === EMPTY) {
18
+ return selector(value);
19
+ }
20
+ const slice = selector(value, prevSlice);
21
+ return equalityFn(prevSlice, slice) ? prevSlice : slice;
22
+ };
23
+ const derivedAtom = atom((get) => {
24
+ const prev = get(derivedAtom);
25
+ const value = get(anAtom);
26
+ return selectValue([value, prev]);
27
+ });
28
+ derivedAtom.init = EMPTY;
29
+ return derivedAtom;
30
+ }, anAtom, selector, equalityFn);
31
+ }
32
+
33
+ // node_modules/jotai/dist/vanilla/utils/constants.js
34
+ var RESET = /* @__PURE__ */ Symbol(process.env.NODE_ENV !== "production" ? "RESET" : "");
35
+
36
+ // node_modules/jotai/dist/vanilla/utils/atomWithStorage.js
37
+ var isPromiseLike = (x) => typeof x?.then === "function";
38
+ function createJSONStorage(getStringStorage = () => {
39
+ try {
40
+ return window.localStorage;
41
+ } catch (e) {
42
+ if (process.env.NODE_ENV !== "production") {
43
+ if (typeof window !== "undefined") {
44
+ console.warn(e);
45
+ }
46
+ }
47
+ return void 0;
48
+ }
49
+ }, options) {
50
+ let lastStr;
51
+ let lastValue;
52
+ const storage = {
53
+ getItem: (key, initialValue) => {
54
+ const parse = (str2) => {
55
+ str2 = str2 || "";
56
+ if (lastStr !== str2) {
57
+ try {
58
+ lastValue = JSON.parse(str2, options?.reviver);
59
+ } catch {
60
+ return initialValue;
61
+ }
62
+ lastStr = str2;
63
+ }
64
+ return lastValue;
65
+ };
66
+ const str = getStringStorage()?.getItem(key) ?? null;
67
+ if (isPromiseLike(str)) {
68
+ return str.then(parse);
69
+ }
70
+ return parse(str);
71
+ },
72
+ setItem: (key, newValue) => getStringStorage()?.setItem(key, JSON.stringify(newValue, options?.replacer)),
73
+ removeItem: (key) => getStringStorage()?.removeItem(key)
74
+ };
75
+ const createHandleSubscribe = (subscriber2) => (key, callback, initialValue) => subscriber2(key, (v) => {
76
+ let newValue;
77
+ try {
78
+ newValue = JSON.parse(v || "", options?.reviver);
79
+ } catch {
80
+ newValue = initialValue;
81
+ }
82
+ callback(newValue);
83
+ });
84
+ let subscriber;
85
+ try {
86
+ subscriber = getStringStorage()?.subscribe;
87
+ } catch {
88
+ }
89
+ if (!subscriber && typeof window !== "undefined" && typeof window.addEventListener === "function" && window.Storage) {
90
+ subscriber = (key, callback) => {
91
+ if (!(getStringStorage() instanceof window.Storage)) {
92
+ return () => {
93
+ };
94
+ }
95
+ const storageEventCallback = (e) => {
96
+ if (e.storageArea === getStringStorage() && e.key === key) {
97
+ callback(e.newValue);
98
+ }
99
+ };
100
+ window.addEventListener("storage", storageEventCallback);
101
+ return () => {
102
+ window.removeEventListener("storage", storageEventCallback);
103
+ };
104
+ };
105
+ }
106
+ if (subscriber) {
107
+ storage.subscribe = createHandleSubscribe(subscriber);
108
+ }
109
+ return storage;
110
+ }
111
+ var defaultStorage = createJSONStorage();
112
+ function atomWithStorage(key, initialValue, storage = defaultStorage, options) {
113
+ const getOnInit = options?.getOnInit;
114
+ const baseAtom = atom(getOnInit ? storage.getItem(key, initialValue) : initialValue);
115
+ if (process.env.NODE_ENV !== "production") {
116
+ baseAtom.debugPrivate = true;
117
+ }
118
+ baseAtom.onMount = (setAtom) => {
119
+ setAtom(storage.getItem(key, initialValue));
120
+ return storage.subscribe?.(key, setAtom, initialValue);
121
+ };
122
+ const anAtom = atom((get) => get(baseAtom), (get, set, update) => {
123
+ const nextValue = typeof update === "function" ? update(get(baseAtom)) : update;
124
+ if (nextValue === RESET) {
125
+ set(baseAtom, initialValue);
126
+ return storage.removeItem(key);
127
+ }
128
+ if (isPromiseLike(nextValue)) {
129
+ return nextValue.then((resolvedValue) => {
130
+ set(baseAtom, resolvedValue);
131
+ return storage.setItem(key, resolvedValue);
132
+ });
133
+ }
134
+ set(baseAtom, nextValue);
135
+ return storage.setItem(key, nextValue);
136
+ });
137
+ return anAtom;
138
+ }
139
+
140
+ // node_modules/jotai/dist/vanilla/utils/unwrap.js
141
+ var getCached2 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
142
+ var cache12 = /* @__PURE__ */ new WeakMap();
143
+ var memo2 = (create, dep1, dep2) => {
144
+ const cache2 = getCached2(() => /* @__PURE__ */ new WeakMap(), cache12, dep1);
145
+ return getCached2(create, cache2, dep2);
146
+ };
147
+ var isPromiseLike2 = (p) => typeof p?.then === "function";
148
+ var defaultFallback = () => void 0;
149
+ function unwrap(anAtom, fallback = defaultFallback) {
150
+ return memo2(() => {
151
+ const promiseErrorCache = /* @__PURE__ */ new WeakMap();
152
+ const promiseResultCache = /* @__PURE__ */ new WeakMap();
153
+ const refreshAtom = atom(0);
154
+ const triggerRefreshAtom = atom([]);
155
+ triggerRefreshAtom.INTERNAL_onInit = (store) => {
156
+ store.set(triggerRefreshAtom, [
157
+ () => store.set(refreshAtom, (c) => c + 1)
158
+ ]);
159
+ };
160
+ if (process.env.NODE_ENV !== "production") {
161
+ refreshAtom.debugPrivate = true;
162
+ triggerRefreshAtom.debugPrivate = true;
163
+ }
164
+ const promiseAndValueAtom = atom((get) => {
165
+ get(refreshAtom);
166
+ let prev;
167
+ try {
168
+ prev = get(promiseAndValueAtom);
169
+ } catch {
170
+ }
171
+ const promise = get(anAtom);
172
+ if (!isPromiseLike2(promise)) {
173
+ return { v: promise };
174
+ }
175
+ if (promise !== prev?.p) {
176
+ promise.then((v) => {
177
+ promiseResultCache.set(promise, v);
178
+ const [triggerRefresh] = get(triggerRefreshAtom);
179
+ triggerRefresh();
180
+ }, (e) => {
181
+ promiseErrorCache.set(promise, e);
182
+ const [triggerRefresh] = get(triggerRefreshAtom);
183
+ triggerRefresh();
184
+ });
185
+ }
186
+ if (promiseErrorCache.has(promise)) {
187
+ if (prev && "e" in prev && prev.p === promise) {
188
+ return prev;
189
+ }
190
+ const e = promiseErrorCache.get(promise);
191
+ if (prev && "v" in prev) {
192
+ return { p: promise, e, v: prev.v };
193
+ }
194
+ return { p: promise, e };
195
+ }
196
+ if (promiseResultCache.has(promise)) {
197
+ return {
198
+ p: promise,
199
+ v: promiseResultCache.get(promise)
200
+ };
201
+ }
202
+ if (prev && "v" in prev) {
203
+ return { p: promise, f: fallback(prev.v), v: prev.v };
204
+ }
205
+ return { p: promise, f: fallback() };
206
+ });
207
+ promiseAndValueAtom.init = void 0;
208
+ if (process.env.NODE_ENV !== "production") {
209
+ promiseAndValueAtom.debugPrivate = true;
210
+ }
211
+ return atom((get) => {
212
+ const state = get(promiseAndValueAtom);
213
+ if ("e" in state) {
214
+ throw state.e;
215
+ }
216
+ if ("f" in state) {
217
+ return state.f;
218
+ }
219
+ return state.v;
220
+ }, (_get, set, ...args) => set(anAtom, ...args));
221
+ }, anAtom, fallback);
222
+ }
223
+
224
+ export {
225
+ selectAtom,
226
+ atomWithStorage,
227
+ unwrap
228
+ };
@@ -1,7 +1,7 @@
1
1
  // package.json with { type: 'json' }
2
2
  var package_default = {
3
3
  name: "alinea",
4
- version: "2.0.0-preview.3",
4
+ version: "2.0.0-preview.4",
5
5
  description: "Headless git-based CMS",
6
6
  repository: "github:alineacms/alinea",
7
7
  license: "MIT",
package/dist/cli/Serve.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "../chunks/chunk-HFBZMKIN.js";
3
+ } from "../chunks/chunk-XMOVGDFI.js";
4
4
  import "../chunks/chunk-CQ52GEHY.js";
5
5
 
6
6
  // src/cli/Serve.ts
package/dist/cli/bin.js CHANGED
@@ -220,7 +220,7 @@ var lib_default2 = (e, t2) => new o(e, t2);
220
220
  // package.json
221
221
  var package_default = {
222
222
  name: "alinea",
223
- version: "2.0.0-preview.3",
223
+ version: "2.0.0-preview.4",
224
224
  description: "Headless git-based CMS",
225
225
  repository: "github:alineacms/alinea",
226
226
  license: "MIT",
@@ -9,7 +9,7 @@ var LocalAuth = class {
9
9
  this.#user = user;
10
10
  }
11
11
  async authenticate() {
12
- return new Response("ok");
12
+ throw new Error("Local authentication is not supported");
13
13
  }
14
14
  async verify(request) {
15
15
  const ctx = this.#context;
@@ -1,3 +1,4 @@
1
+ import type { BackendCapabilities } from 'alinea/core/Connection';
1
2
  import type { User } from 'alinea/core/User';
2
3
  export declare enum AuthResultType {
3
4
  Authenticated = 0,
@@ -8,6 +9,7 @@ export declare enum AuthResultType {
8
9
  export type AuthResult = {
9
10
  type: AuthResultType.Authenticated;
10
11
  user: User;
12
+ capabilities?: BackendCapabilities;
11
13
  } | {
12
14
  type: AuthResultType.UnAuthenticated;
13
15
  redirect: string;
@@ -0,0 +1,7 @@
1
+ interface VerifyCloudHandshakeOptions {
2
+ clientId: string;
3
+ handshakeId: string;
4
+ origin: string;
5
+ }
6
+ export declare function verifyCloudHandshake(token: string, options: VerifyCloudHandshakeOptions): Promise<void>;
7
+ export {};
@@ -0,0 +1,64 @@
1
+ import "../chunks/chunk-CQ52GEHY.js";
2
+
3
+ // src/cloud/CloudHandshake.ts
4
+ import { decode, verify } from "alinea/core/util/JWT";
5
+ import { isRecord } from "alinea/core/util/Objects";
6
+ import { cloudConfig } from "./CloudConfig.js";
7
+ var keysPromise;
8
+ var keysExpireAt = 0;
9
+ var lastForcedRefreshAt = 0;
10
+ var keyCacheLifetime = 5 * 60 * 1e3;
11
+ var forcedRefreshInterval = 60 * 1e3;
12
+ async function verifyCloudHandshake(token, options) {
13
+ const { header } = decode(token);
14
+ if (header.alg !== "RS256" || typeof header.kid !== "string")
15
+ throw new Error("Invalid handshake token header");
16
+ let key = (await cloudKeys()).find((key2) => key2.kid === header.kid);
17
+ if (!key) {
18
+ key = (await refreshCloudKeys()).find((key2) => key2.kid === header.kid);
19
+ }
20
+ if (!key) throw new Error("Unknown handshake signing key");
21
+ const payload = await verify(token, key, { algorithms: ["RS256"] });
22
+ if (!isRecord(payload) || payload.purpose !== "handshake" || payload.handshake_id !== options.handshakeId || payload.aud !== options.clientId || payload.iss !== normalizedCloudUrl() || payload.origin !== options.origin || typeof payload.project !== "string" || typeof payload.iat !== "number" || typeof payload.exp !== "number") {
23
+ throw new Error("Invalid handshake token claims");
24
+ }
25
+ }
26
+ function cloudKeys() {
27
+ if (keysPromise && (keysExpireAt === 0 || Date.now() < keysExpireAt))
28
+ return keysPromise;
29
+ return loadCloudKeys();
30
+ }
31
+ function refreshCloudKeys() {
32
+ const now = Date.now();
33
+ if (keysPromise && keysExpireAt === 0) return keysPromise;
34
+ if (keysPromise && now - lastForcedRefreshAt < forcedRefreshInterval)
35
+ return keysPromise;
36
+ lastForcedRefreshAt = now;
37
+ return loadCloudKeys();
38
+ }
39
+ function loadCloudKeys() {
40
+ keysExpireAt = 0;
41
+ keysPromise = fetch(cloudConfig.jwks).then(async (response) => {
42
+ if (!response.ok)
43
+ throw new Error(`Could not load handshake keys: ${response.status}`);
44
+ const body = await response.json();
45
+ if (!isRecord(body) || !Array.isArray(body.keys))
46
+ throw new Error("Invalid handshake key response");
47
+ keysExpireAt = Date.now() + keyCacheLifetime;
48
+ return body.keys.filter(isCloudKey);
49
+ }).catch((cause) => {
50
+ keysPromise = void 0;
51
+ keysExpireAt = 0;
52
+ throw cause;
53
+ });
54
+ return keysPromise;
55
+ }
56
+ function isCloudKey(value) {
57
+ return isRecord(value) && typeof value.kid === "string";
58
+ }
59
+ function normalizedCloudUrl() {
60
+ return cloudConfig.url.replace(/\/$/, "");
61
+ }
62
+ export {
63
+ verifyCloudHandshake
64
+ };
@@ -10,12 +10,15 @@ import type { User, UserInput } from 'alinea/core/User';
10
10
  export declare class CloudRemote extends OAuth2 implements RemoteConnection {
11
11
  #private;
12
12
  constructor(context: RequestContext, config: Config);
13
+ capabilities(): Promise<{
14
+ users: boolean;
15
+ }>;
13
16
  getTreeIfDifferent(sha: string): Promise<ReadonlyTree | undefined>;
14
17
  getBlobs(shas: ReadonlyArray<string>, options?: GetBlobsOptions): AsyncGenerator<[sha: string, blob: Uint8Array]>;
15
18
  write(request: CommitRequest): Promise<{
16
19
  sha: string;
17
20
  }>;
18
- authenticate(request: Request, options?: AuthOptions): Promise<globalThis.Response>;
21
+ authenticate(request: Request, options: AuthOptions): Promise<globalThis.Response>;
19
22
  prepareUpload(file: string, metadata?: UploadMetadata): Promise<{
20
23
  entryId: string;
21
24
  location: string;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "../chunks/chunk-HFBZMKIN.js";
3
+ } from "../chunks/chunk-XMOVGDFI.js";
4
4
  import "../chunks/chunk-CQ52GEHY.js";
5
5
 
6
6
  // src/cloud/CloudRemote.ts
@@ -20,6 +20,7 @@ import { Workspace } from "alinea/core/Workspace";
20
20
  import { Response } from "@alinea/iso";
21
21
  import { AuthResultType } from "./AuthResult.js";
22
22
  import { cloudConfig } from "./CloudConfig.js";
23
+ import { verifyCloudHandshake } from "./CloudHandshake.js";
23
24
  var CloudRemote = class extends OAuth2 {
24
25
  #context;
25
26
  #config;
@@ -42,6 +43,9 @@ var CloudRemote = class extends OAuth2 {
42
43
  this.#context = context;
43
44
  this.#config = config;
44
45
  }
46
+ async capabilities() {
47
+ return { users: false };
48
+ }
45
49
  async getTreeIfDifferent(sha) {
46
50
  const ctx = this.#context;
47
51
  return parseOutcome(
@@ -122,13 +126,27 @@ var CloudRemote = class extends OAuth2 {
122
126
  // The cloud server will request a handshake confirmation on this route
123
127
  case AuthAction.Handshake: {
124
128
  const handShakeId = url.searchParams.get("handshake_id");
125
- if (!handShakeId)
129
+ const handshakeToken = url.searchParams.get("handshake_token");
130
+ if (!handShakeId || !handshakeToken)
126
131
  throw new HttpError(
127
132
  400,
128
- "Provide a valid handshake id to initiate handshake"
133
+ "Provide valid handshake credentials to initiate handshake"
129
134
  );
135
+ const clientId = ctx.apiKey.split("_")[1];
136
+ if (!clientId)
137
+ throw new HttpError(401, "A Cloud API key is required for handshake");
138
+ try {
139
+ await verifyCloudHandshake(handshakeToken, {
140
+ clientId,
141
+ handshakeId: handShakeId,
142
+ origin: new URL(ctx.handlerUrl).origin
143
+ });
144
+ } catch (cause) {
145
+ throw new HttpError(401, "Invalid handshake token", { cause });
146
+ }
130
147
  const body = {
131
148
  handshake_id: handShakeId,
149
+ handshake_token: handshakeToken,
132
150
  status: {
133
151
  version: package_default.version,
134
152
  roles: entries(this.#config.roles ?? {}).map(([name, role]) => {
@@ -27,17 +27,17 @@ import {
27
27
 
28
28
  // src/components/Calendar.module.css
29
29
  var Calendar_default = {
30
- "Calendar-cell": "alinea-Calendar-cell",
31
- "CalendarCell": "alinea-Calendar-cell",
30
+ "Calendar-button": "alinea-Calendar-button",
31
+ "CalendarButton": "alinea-Calendar-button",
32
32
  "Calendar-grid": "alinea-Calendar-grid",
33
33
  "CalendarGrid": "alinea-Calendar-grid",
34
+ "Calendar-cell": "alinea-Calendar-cell",
35
+ "CalendarCell": "alinea-Calendar-cell",
36
+ "Calendar": "alinea-Calendar",
34
37
  "Calendar-header": "alinea-Calendar-header",
35
38
  "CalendarHeader": "alinea-Calendar-header",
36
- "Calendar-button": "alinea-Calendar-button",
37
- "CalendarButton": "alinea-Calendar-button",
38
39
  "Calendar-heading": "alinea-Calendar-heading",
39
- "CalendarHeading": "alinea-Calendar-heading",
40
- "Calendar": "alinea-Calendar"
40
+ "CalendarHeading": "alinea-Calendar-heading"
41
41
  };
42
42
 
43
43
  // src/components/Calendar.tsx
@@ -16,11 +16,11 @@ import "../chunks/chunk-CQ52GEHY.js";
16
16
 
17
17
  // src/components/Checkbox.module.css
18
18
  var Checkbox_default = {
19
+ "Checkbox": "alinea-Checkbox",
19
20
  "Checkbox-box": "alinea-Checkbox-box",
20
21
  "CheckboxBox": "alinea-Checkbox-box",
21
22
  "Checkbox-mark": "alinea-Checkbox-mark",
22
- "CheckboxMark": "alinea-Checkbox-mark",
23
- "Checkbox": "alinea-Checkbox"
23
+ "CheckboxMark": "alinea-Checkbox-mark"
24
24
  };
25
25
 
26
26
  // src/components/Checkbox.tsx
@@ -29,24 +29,24 @@ import {
29
29
 
30
30
  // src/components/ComboBox.module.css
31
31
  var ComboBox_default = {
32
- "ComboBoxItem": "alinea-ComboBoxItem",
33
- "ComboBoxTrigger-button-arrow": "alinea-ComboBoxTrigger-button-arrow",
34
- "ComboBoxTriggerButtonArrow": "alinea-ComboBoxTrigger-button-arrow",
35
- "ComboBoxTrigger-button": "alinea-ComboBoxTrigger-button",
36
- "ComboBoxTriggerButton": "alinea-ComboBoxTrigger-button",
37
- "ComboBoxTrigger": "alinea-ComboBoxTrigger",
38
- "ComboBoxTrigger-actions": "alinea-ComboBoxTrigger-actions",
39
- "ComboBoxTriggerActions": "alinea-ComboBoxTrigger-actions",
40
32
  "ComboBoxPopover-listbox": "alinea-ComboBoxPopover-listbox",
41
33
  "ComboBoxPopoverListbox": "alinea-ComboBoxPopover-listbox",
42
- "ComboBoxClear": "alinea-ComboBoxClear",
43
- "ComboBoxTrigger-input": "alinea-ComboBoxTrigger-input",
44
- "ComboBoxTriggerInput": "alinea-ComboBoxTrigger-input",
45
34
  "ComboBoxItem-check": "alinea-ComboBoxItem-check",
46
35
  "ComboBoxItemCheck": "alinea-ComboBoxItem-check",
36
+ "ComboBoxTrigger-actions": "alinea-ComboBoxTrigger-actions",
37
+ "ComboBoxTriggerActions": "alinea-ComboBoxTrigger-actions",
38
+ "ComboBox": "alinea-ComboBox",
47
39
  "ComboBoxTrigger-button-value": "alinea-ComboBoxTrigger-button-value",
48
40
  "ComboBoxTriggerButtonValue": "alinea-ComboBoxTrigger-button-value",
49
- "ComboBox": "alinea-ComboBox"
41
+ "ComboBoxTrigger-button-arrow": "alinea-ComboBoxTrigger-button-arrow",
42
+ "ComboBoxTriggerButtonArrow": "alinea-ComboBoxTrigger-button-arrow",
43
+ "ComboBoxTrigger": "alinea-ComboBoxTrigger",
44
+ "ComboBoxClear": "alinea-ComboBoxClear",
45
+ "ComboBoxItem": "alinea-ComboBoxItem",
46
+ "ComboBoxTrigger-button": "alinea-ComboBoxTrigger-button",
47
+ "ComboBoxTriggerButton": "alinea-ComboBoxTrigger-button",
48
+ "ComboBoxTrigger-input": "alinea-ComboBoxTrigger-input",
49
+ "ComboBoxTriggerInput": "alinea-ComboBoxTrigger-input"
50
50
  };
51
51
 
52
52
  // src/components/ComboBox.tsx