alinea 1.3.1 → 1.4.0-preview.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 (64) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/LICENSES.md +80 -80
  3. package/dist/adapter/next/cms.js +1 -1
  4. package/dist/backend/Handler.js +19 -8
  5. package/dist/backend/api/GithubApi.js +43 -12
  6. package/dist/chunks/{chunk-V4O6S3PC.js → chunk-LIA6NPBB.js} +1 -1
  7. package/dist/cli/Serve.js +1 -1
  8. package/dist/cli/bin.js +1 -1
  9. package/dist/cloud/CloudRemote.js +24 -10
  10. package/dist/core/Graph.js +2 -1
  11. package/dist/core/Outcome.d.ts +2 -1
  12. package/dist/core/Outcome.js +10 -4
  13. package/dist/core/db/EntryIndex.d.ts +9 -3
  14. package/dist/core/db/EntryIndex.js +55 -35
  15. package/dist/core/db/EntryTransaction.d.ts +2 -1
  16. package/dist/core/db/EntryTransaction.js +59 -31
  17. package/dist/core/db/LocalDB.js +11 -3
  18. package/dist/core/db/Mutation.d.ts +6 -1
  19. package/dist/core/db/Operation.d.ts +7 -0
  20. package/dist/core/db/Operation.js +20 -9
  21. package/dist/core/db/WriteableGraph.d.ts +5 -4
  22. package/dist/core/db/WriteableGraph.js +14 -10
  23. package/dist/core/source/FSSource.d.ts +0 -2
  24. package/dist/core/source/FSSource.js +0 -13
  25. package/dist/core/source/GithubSource.d.ts +1 -0
  26. package/dist/core/source/GithubSource.js +11 -11
  27. package/dist/dashboard/Routes.d.ts +4 -0
  28. package/dist/dashboard/atoms/DbAtoms.d.ts +1 -1
  29. package/dist/dashboard/atoms/DbAtoms.js +7 -14
  30. package/dist/dashboard/atoms/EntryAtoms.d.ts +2 -0
  31. package/dist/dashboard/atoms/EntryAtoms.js +25 -0
  32. package/dist/dashboard/atoms/EntryEditorAtoms.d.ts +15 -5
  33. package/dist/dashboard/atoms/EntryEditorAtoms.js +38 -30
  34. package/dist/dashboard/boot/DashboardWorker.js +12 -11
  35. package/dist/dashboard/editor/DefaultViews.d.ts +2 -1
  36. package/dist/dashboard/view/EntryEdit.js +3 -3
  37. package/dist/dashboard/view/EntryTree.js +126 -80
  38. package/dist/dashboard/view/Sidebar.js +9 -1
  39. package/dist/dashboard/view/entry/EntryHeader.js +47 -23
  40. package/dist/dashboard/view/entry/NewEntry.js +5 -3
  41. package/dist/field/list/ListField.view.d.ts +1 -1
  42. package/dist/field/list/ListField.view.js +3 -3
  43. package/dist/field/object/ObjectField.d.ts +12 -4
  44. package/dist/index.css +130 -55
  45. package/dist/test/status.test.d.ts +1 -0
  46. package/dist/ui/AppBar.d.ts +1 -1
  47. package/dist/ui/AppBar.js +2 -0
  48. package/dist/ui/Button.d.ts +1 -1
  49. package/dist/ui/Button.js +13 -5
  50. package/dist/ui/icons/IcBaselinePause.d.ts +2 -0
  51. package/dist/ui/icons/IcBaselinePause.js +20 -0
  52. package/dist/ui/icons/IcOutlineArchive.d.ts +2 -0
  53. package/dist/ui/icons/IcOutlineArchive.js +26 -0
  54. package/dist/ui/icons/IcOutlineFolder.d.ts +2 -0
  55. package/dist/ui/icons/IcOutlineFolder.js +26 -0
  56. package/dist/ui/icons/IcRoundNotes.d.ts +0 -1
  57. package/dist/ui/icons/IcRoundNotes.js +1 -3
  58. package/dist/ui/icons/IcTwotoneDescription.d.ts +2 -0
  59. package/dist/ui/icons/IcTwotoneDescription.js +37 -0
  60. package/dist/ui/icons/IcTwotoneFolder.d.ts +2 -0
  61. package/dist/ui/icons/IcTwotoneFolder.js +37 -0
  62. package/dist/ui/icons/IcTwotoneInsertDriveFile.d.ts +2 -0
  63. package/dist/ui/icons/IcTwotoneInsertDriveFile.js +30 -0
  64. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  {
2
- "_id": "2ygHI5LHHVmR2H8kYrePnoHLbcB",
2
+ "_id": "2zEEsGEasvfbFJSwme8hbd6n5z2",
3
3
  "_type": "Page",
4
4
  "_index": "a0",
5
5
  "_seeded": "welcome.json",
package/dist/LICENSES.md CHANGED
@@ -26,33 +26,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
26
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
27
  SOFTWARE.
28
28
 
29
- ===
30
-
31
- # react-query@3.39.3 (MIT)
32
-
33
- MIT License
34
-
35
- Copyright (c) 2019 Tanner Linsley
36
-
37
- Permission is hereby granted, free of charge, to any person obtaining a copy
38
- of this software and associated documentation files (the "Software"), to deal
39
- in the Software without restriction, including without limitation the rights
40
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41
- copies of the Software, and to permit persons to whom the Software is
42
- furnished to do so, subject to the following conditions:
43
-
44
- The above copyright notice and this permission notice shall be included in all
45
- copies or substantial portions of the Software.
46
-
47
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53
- SOFTWARE.
54
-
55
-
56
29
  ===
57
30
 
58
31
  # lib0@0.2.88 (MIT)
@@ -131,28 +104,29 @@ IN THE SOFTWARE.
131
104
 
132
105
  ===
133
106
 
134
- # @popperjs/core@2.11.8 (MIT)
107
+ # react-query@3.39.3 (MIT)
135
108
 
136
- The MIT License (MIT)
109
+ MIT License
137
110
 
138
- Copyright (c) 2019 Federico Zivolo
111
+ Copyright (c) 2019 Tanner Linsley
139
112
 
140
- Permission is hereby granted, free of charge, to any person obtaining a copy of
141
- this software and associated documentation files (the "Software"), to deal in
142
- the Software without restriction, including without limitation the rights to
143
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
144
- the Software, and to permit persons to whom the Software is furnished to do so,
145
- subject to the following conditions:
113
+ Permission is hereby granted, free of charge, to any person obtaining a copy
114
+ of this software and associated documentation files (the "Software"), to deal
115
+ in the Software without restriction, including without limitation the rights
116
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
117
+ copies of the Software, and to permit persons to whom the Software is
118
+ furnished to do so, subject to the following conditions:
146
119
 
147
120
  The above copyright notice and this permission notice shall be included in all
148
121
  copies or substantial portions of the Software.
149
122
 
150
123
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
152
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
153
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
154
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
155
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
124
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
125
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
126
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
127
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
128
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
129
+ SOFTWARE.
156
130
 
157
131
 
158
132
  ===
@@ -206,6 +180,32 @@ THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRE
206
180
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
207
181
 
208
182
 
183
+ ===
184
+
185
+ # @popperjs/core@2.11.8 (MIT)
186
+
187
+ The MIT License (MIT)
188
+
189
+ Copyright (c) 2019 Federico Zivolo
190
+
191
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
192
+ this software and associated documentation files (the "Software"), to deal in
193
+ the Software without restriction, including without limitation the rights to
194
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
195
+ the Software, and to permit persons to whom the Software is furnished to do so,
196
+ subject to the following conditions:
197
+
198
+ The above copyright notice and this permission notice shall be included in all
199
+ copies or substantial portions of the Software.
200
+
201
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
202
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
203
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
204
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
205
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
206
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
207
+
208
+
209
209
  ===
210
210
 
211
211
  # prop-types@15.8.1 (MIT)
@@ -440,18 +440,6 @@ SOFTWARE.
440
440
  limitations under the License.
441
441
 
442
442
 
443
- ===
444
-
445
- # @headless-tree/react@0.0.15 (MIT)
446
-
447
- MIT
448
-
449
- ===
450
-
451
- # @headless-tree/core@0.0.15 (MIT)
452
-
453
- MIT
454
-
455
443
  ===
456
444
 
457
445
  # react-is@16.13.1 (MIT)
@@ -496,6 +484,18 @@ The above copyright notice and this permission notice shall be included in all c
496
484
  THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
497
485
 
498
486
 
487
+ ===
488
+
489
+ # @headless-tree/core@0.0.15 (MIT)
490
+
491
+ MIT
492
+
493
+ ===
494
+
495
+ # @headless-tree/react@0.0.15 (MIT)
496
+
497
+ MIT
498
+
499
499
  ===
500
500
 
501
501
  # y-prosemirror@1.2.15 (MIT)
@@ -1585,6 +1585,33 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1585
1585
  See the License for the specific language governing permissions and
1586
1586
  limitations under the License.
1587
1587
 
1588
+ ===
1589
+
1590
+ # @tanstack/virtual-core@3.10.6 (MIT)
1591
+
1592
+ MIT License
1593
+
1594
+ Copyright (c) 2021-present Tanner Linsley
1595
+
1596
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1597
+ of this software and associated documentation files (the "Software"), to deal
1598
+ in the Software without restriction, including without limitation the rights
1599
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1600
+ copies of the Software, and to permit persons to whom the Software is
1601
+ furnished to do so, subject to the following conditions:
1602
+
1603
+ The above copyright notice and this permission notice shall be included in all
1604
+ copies or substantial portions of the Software.
1605
+
1606
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1607
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1608
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1609
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1610
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1611
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1612
+ SOFTWARE.
1613
+
1614
+
1588
1615
  ===
1589
1616
 
1590
1617
  # @react-stately/utils@3.10.5 (Apache-2.0)
@@ -1790,30 +1817,3 @@ limitations under the License.
1790
1817
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1791
1818
  See the License for the specific language governing permissions and
1792
1819
  limitations under the License.
1793
-
1794
-
1795
- ===
1796
-
1797
- # @tanstack/virtual-core@3.10.6 (MIT)
1798
-
1799
- MIT License
1800
-
1801
- Copyright (c) 2021-present Tanner Linsley
1802
-
1803
- Permission is hereby granted, free of charge, to any person obtaining a copy
1804
- of this software and associated documentation files (the "Software"), to deal
1805
- in the Software without restriction, including without limitation the rights
1806
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1807
- copies of the Software, and to permit persons to whom the Software is
1808
- furnished to do so, subject to the following conditions:
1809
-
1810
- The above copyright notice and this permission notice shall be included in all
1811
- copies or substantial portions of the Software.
1812
-
1813
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1814
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1815
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1816
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1817
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1818
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1819
- SOFTWARE.
@@ -63,7 +63,7 @@ var NextCMS = class extends CMS {
63
63
  const { PHASE_PRODUCTION_BUILD } = await import("next/constants");
64
64
  const isBuild = process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD;
65
65
  const { db, previews } = await this.init;
66
- const sync = () => db.syncWith(client);
66
+ const sync = () => db.syncWith(client).catch(console.error);
67
67
  if (!isBuild) {
68
68
  if (preview) {
69
69
  preview = await previews.parse(preview, sync);
@@ -16,6 +16,7 @@ import { JWTPreviews } from "alinea/backend/util/JWTPreviews";
16
16
  import { CloudRemote } from "alinea/cloud/CloudRemote";
17
17
  import { HttpError } from "alinea/core/HttpError";
18
18
  import { getScope } from "alinea/core/Scope";
19
+ import { ShaMismatchError } from "alinea/core/source/ShaMismatchError";
19
20
  import { base64 } from "alinea/core/util/Encoding";
20
21
  import { HandleAction } from "./HandleAction.js";
21
22
  import { createPreviewParser } from "./resolver/ParsePreview.js";
@@ -118,14 +119,24 @@ function createHandler({
118
119
  expectUser();
119
120
  expectJson();
120
121
  const mutations = await body;
121
- const request2 = await local.request(mutations);
122
- const { sha } = await cnx.write(request2);
123
- if (sha === request2.intoSha) {
124
- await local.write(request2);
125
- } else {
122
+ const attempt = async (retry = 0) => {
126
123
  await local.syncWith(cnx);
127
- }
128
- return Response.json({ sha });
124
+ const request2 = await local.request(mutations);
125
+ try {
126
+ let { sha } = await cnx.write(request2);
127
+ if (sha === request2.intoSha) {
128
+ await local.write(request2);
129
+ } else {
130
+ sha = await local.syncWith(cnx);
131
+ }
132
+ return sha;
133
+ } catch (error) {
134
+ if (error instanceof ShaMismatchError && retry < 3)
135
+ return attempt(retry + 1);
136
+ throw error;
137
+ }
138
+ };
139
+ return Response.json({ sha: await attempt() });
129
140
  }
130
141
  if (action === HandleAction.Commit && request.method === "POST") {
131
142
  throw new Error("Mutations expected");
@@ -141,7 +152,7 @@ function createHandler({
141
152
  if (action === HandleAction.Tree && request.method === "GET") {
142
153
  expectJson();
143
154
  const sha = string(url.searchParams.get("sha"));
144
- await periodicSync(cnx);
155
+ await local.syncWith(cnx);
145
156
  const tree = await local.getTreeIfDifferent(sha);
146
157
  return Response.json(tree ?? null);
147
158
  }
@@ -5,6 +5,7 @@ import { HttpError } from "alinea/core/HttpError";
5
5
  import {
6
6
  GithubSource
7
7
  } from "alinea/core/source/GithubSource";
8
+ import { ShaMismatchError } from "alinea/core/source/ShaMismatchError";
8
9
  import { base64, btoa } from "alinea/core/util/Encoding";
9
10
  import { join } from "alinea/core/util/Paths";
10
11
  var GithubApi = class extends GithubSource {
@@ -14,6 +15,10 @@ var GithubApi = class extends GithubSource {
14
15
  this.#options = options;
15
16
  }
16
17
  async write(request) {
18
+ const currentCommit = await getLatestCommitOid(this.#options);
19
+ const currentSha = await this.shaAt(currentCommit);
20
+ if (currentSha !== request.fromSha)
21
+ throw new ShaMismatchError(currentSha, request.fromSha);
17
22
  const { author } = this.#options;
18
23
  let commitMessage = request.description;
19
24
  if (author) {
@@ -21,8 +26,13 @@ var GithubApi = class extends GithubSource {
21
26
 
22
27
  Co-authored-by: ${author.name} <${author.email}>`;
23
28
  }
24
- await applyChangesToRepo(this.#options, request.changes, commitMessage);
25
- return this.getTree().then((tree) => ({ sha: tree.sha }));
29
+ const newCommit = await applyChangesToRepo(
30
+ this.#options,
31
+ currentCommit,
32
+ request.changes,
33
+ commitMessage
34
+ );
35
+ return { sha: await this.shaAt(newCommit) };
26
36
  }
27
37
  async revisions(file) {
28
38
  return getFileCommitHistory(this.#options, file);
@@ -51,6 +61,13 @@ function graphQL(query, variables, token) {
51
61
  }).then(async (response) => {
52
62
  if (response.ok) return response.json();
53
63
  throw new HttpError(response.status, await response.text());
64
+ }).then((result) => {
65
+ if (Array.isArray(result.errors) && result.errors.length > 0) {
66
+ const message = result.errors.map((e) => e.message).join("; ");
67
+ console.trace(result.errors);
68
+ throw new Error(message);
69
+ }
70
+ return result;
54
71
  });
55
72
  }
56
73
  async function getFileCommitHistory({ owner, repo, branch, authToken, rootDir }, file) {
@@ -104,7 +121,7 @@ async function getFileContentAtCommit({ owner, repo, authToken, rootDir }, file,
104
121
  );
105
122
  return result.data.repository.object?.text;
106
123
  }
107
- async function applyChangesToRepo(options, changes, commitMessage) {
124
+ async function applyChangesToRepo(options, expectedHeadOid, changes, commitMessage) {
108
125
  const { additions, deletions } = await processChanges(options, changes);
109
126
  const { owner, repo, branch, authToken } = options;
110
127
  return graphQL(
@@ -121,18 +138,32 @@ async function applyChangesToRepo(options, changes, commitMessage) {
121
138
  repositoryNameWithOwner: `${owner}/${repo}`,
122
139
  branchName: branch
123
140
  },
124
- message: {
125
- headline: commitMessage
126
- },
127
- fileChanges: {
128
- additions,
129
- deletions
130
- },
131
- expectedHeadOid: await getLatestCommitOid(options)
141
+ message: { headline: commitMessage },
142
+ fileChanges: { additions, deletions },
143
+ expectedHeadOid
132
144
  }
133
145
  },
134
146
  authToken
135
- ).then((result) => result.data.createCommitOnBranch.commit.oid);
147
+ ).then((result) => {
148
+ const commitId = result.data.createCommitOnBranch.commit.oid;
149
+ return commitId;
150
+ }).catch((error) => {
151
+ if (error instanceof Error) {
152
+ const mismatchMessage = /is at ([a-z0-9]+) but expected ([a-z0-9]+)/;
153
+ const match = error.message.match(mismatchMessage);
154
+ if (match) {
155
+ const [_, actual, expected] = match;
156
+ throw new ShaMismatchError(actual, expected);
157
+ }
158
+ const expectedMessage = /Expected branch to point to "([a-z0-9]+)"/;
159
+ const expectedMatch = error.message.match(expectedMessage);
160
+ if (expectedMatch) {
161
+ const actualSha = expectedMatch[1];
162
+ throw new ShaMismatchError(actualSha, expectedHeadOid);
163
+ }
164
+ }
165
+ throw error;
166
+ });
136
167
  }
137
168
  async function processChanges({ rootDir, contentDir }, changes) {
138
169
  const additions = Array();
@@ -2,7 +2,7 @@
2
2
  var package_default = {
3
3
  bin: "./dist/cli.js",
4
4
  name: "alinea",
5
- version: "1.3.1",
5
+ version: "1.4.0-preview.0",
6
6
  description: "Headless git-based CMS",
7
7
  repository: {
8
8
  type: "git",
package/dist/cli/Serve.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "../chunks/chunk-V4O6S3PC.js";
3
+ } from "../chunks/chunk-LIA6NPBB.js";
4
4
  import "../chunks/chunk-NZLE2WMY.js";
5
5
 
6
6
  // src/cli/Serve.ts
package/dist/cli/bin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "../chunks/chunk-V4O6S3PC.js";
3
+ } from "../chunks/chunk-LIA6NPBB.js";
4
4
  import "../chunks/chunk-NZLE2WMY.js";
5
5
 
6
6
  // node_modules/mri/lib/index.mjs
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "../chunks/chunk-V4O6S3PC.js";
3
+ } from "../chunks/chunk-LIA6NPBB.js";
4
4
  import {
5
5
  PLazy
6
6
  } from "../chunks/chunk-IKINPSS5.js";
@@ -18,6 +18,7 @@ import {
18
18
  import { HttpError } from "alinea/core/HttpError";
19
19
  import { Outcome, outcome } from "alinea/core/Outcome";
20
20
  import { Workspace } from "alinea/core/Workspace";
21
+ import { ShaMismatchError } from "alinea/core/source/ShaMismatchError";
21
22
  import { ReadonlyTree } from "alinea/core/source/Tree";
22
23
  import { base64 } from "alinea/core/util/Encoding";
23
24
  import { verify } from "alinea/core/util/JWT";
@@ -100,7 +101,14 @@ var CloudRemote = class {
100
101
  })
101
102
  })
102
103
  )
103
- );
104
+ ).catch((error) => {
105
+ if (error instanceof HttpError && error.code === 409) {
106
+ const actual = "actualSha" in error && error.actualSha;
107
+ const expected = "expectedSha" in error && error.expectedSha;
108
+ if (actual && expected) throw new ShaMismatchError(actual, expected);
109
+ }
110
+ throw error;
111
+ });
104
112
  }
105
113
  async authenticate(request) {
106
114
  const ctx = this.#context;
@@ -325,15 +333,21 @@ function json(init = {}) {
325
333
  headers.set("accept", "application/json");
326
334
  return { ...init, headers };
327
335
  }
328
- async function failOnHttpError(res) {
329
- if (res.status >= 400) throw new HttpError(res.status, await res.text());
330
- return res;
336
+ async function failOnHttpError(response) {
337
+ if (!response.ok) throw new HttpError(response.status, await response.text());
338
+ return response;
331
339
  }
332
- function parseJson(res) {
333
- return res.json();
334
- }
335
- function parseOutcome(res) {
336
- return res.then(failOnHttpError).then(parseJson).then(Outcome.fromJSON).then(Outcome.unpack);
340
+ async function parseOutcome(expected) {
341
+ const response = await expected;
342
+ const contentType = response.headers.get("content-type");
343
+ const isJson = contentType?.includes("application/json");
344
+ if (!response.ok && !isJson) {
345
+ const message = await response.text();
346
+ throw new HttpError(response.status, message);
347
+ }
348
+ const output = await response.json();
349
+ const outcome2 = Outcome.fromJSON(output, response.status);
350
+ return Outcome.unpack(outcome2);
337
351
  }
338
352
  export {
339
353
  COOKIE_NAME,
@@ -9,8 +9,9 @@ var Graph = class {
9
9
  return this.resolve({ ...query, first: true });
10
10
  }
11
11
  async get(query) {
12
+ const error = globalThis.Bun ? new Error("Entry not found") : void 0;
12
13
  const result = await this.resolve({ ...query, get: true });
13
- if (!result) throw new Error("Entry not found");
14
+ if (!result) throw error ?? new Error("Entry not found");
14
15
  return result;
15
16
  }
16
17
  count(query) {
@@ -1,3 +1,4 @@
1
+ import { type ErrorCode } from './HttpError.js';
1
2
  type ErrorObject = {
2
3
  stack?: string;
3
4
  message?: string;
@@ -21,7 +22,7 @@ export declare namespace outcome {
21
22
  }
22
23
  export type Outcome<T = void> = Outcome.OutcomeImpl<T> & Pair<T>;
23
24
  export declare namespace Outcome {
24
- export function fromJSON<T>(json: OutcomeJSON<T>): Outcome<T>;
25
+ export function fromJSON<T>(json: OutcomeJSON<T>, status?: ErrorCode): Outcome<T>;
25
26
  export function unpack<T>(outcome: Outcome<T>): T;
26
27
  export function isOutcome(value: any): value is Outcome;
27
28
  export function Success<T>(data: T): Outcome<T>;
@@ -2,6 +2,7 @@ import "../chunks/chunk-NZLE2WMY.js";
2
2
 
3
3
  // src/core/Outcome.ts
4
4
  import { HttpError } from "./HttpError.js";
5
+ import { assign } from "./util/Objects.js";
5
6
  function outcome(run) {
6
7
  try {
7
8
  if (typeof run === "function") {
@@ -37,16 +38,21 @@ function isPromiseLike(value) {
37
38
  })(outcome || (outcome = {}));
38
39
  var Outcome;
39
40
  ((Outcome2) => {
40
- function fromJSON(json) {
41
+ function fromJSON(json, status) {
41
42
  if (json.success) return Success(json.data);
42
- const error = new HttpError(json.error.status, json.error.message);
43
- error.stack = json.error.stack;
43
+ const error = new HttpError(
44
+ json.error.status ?? status ?? 500,
45
+ json.error.message ?? "Unknown error"
46
+ );
47
+ assign(error, json.error);
48
+ if (json.error.stack) error.stack = json.error.stack;
44
49
  return Failure(error);
45
50
  }
46
51
  Outcome2.fromJSON = fromJSON;
47
52
  function unpack(outcome2) {
48
53
  if (outcome2.isSuccess()) return outcome2.value;
49
- throw outcome2.error;
54
+ if (outcome2.isFailure()) throw outcome2.error;
55
+ throw new Error("Outcome is neither success nor failure");
50
56
  }
51
57
  Outcome2.unpack = unpack;
52
58
  function isOutcome(value) {
@@ -1,6 +1,5 @@
1
1
  import { Config } from 'alinea/core/Config';
2
- import type { Entry } from 'alinea/core/Entry';
3
- import type { EntryStatus } from 'alinea/core/Entry';
2
+ import type { Entry, EntryStatus } from 'alinea/core/Entry';
4
3
  import type { ChangesBatch } from '../source/Change.js';
5
4
  import { type Source } from '../source/Source.js';
6
5
  import { ReadonlyTree } from '../source/Tree.js';
@@ -31,12 +30,19 @@ export declare class EntryIndex extends EventTarget {
31
30
  indexChanges(batch: ChangesBatch): Promise<string>;
32
31
  updateSearch(entry: Entry): Promise<void>;
33
32
  }
33
+ declare class Versions extends Map<EntryStatus, Entry> {
34
+ inheritedStatus: EntryStatus | undefined;
35
+ setInherited(parentStatus: EntryStatus | undefined): void;
36
+ get active(): Entry | undefined;
37
+ get main(): Entry | undefined;
38
+ versions(): Generator<Entry>;
39
+ }
34
40
  declare class EntryNode {
35
41
  #private;
36
42
  id: string;
37
43
  type: string;
38
44
  byFile: Map<string, Entry>;
39
- locales: Map<string | null, Map<EntryStatus, Entry>>;
45
+ locales: Map<string | null, Versions>;
40
46
  constructor(config: Config, from: Entry);
41
47
  get index(): string;
42
48
  get parentId(): string | null;