@drawnagency/primitives 0.1.97 → 0.1.99

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 (67) hide show
  1. package/dist/{chunk-F2337B35.js → chunk-26ALJO4K.js} +1 -1
  2. package/dist/{chunk-S4L3ZFKM.js → chunk-3COSXTOY.js} +1 -1
  3. package/dist/{chunk-RHWWQV3J.js → chunk-BGHWUJFV.js} +1 -0
  4. package/dist/{chunk-QEHPGA5N.js → chunk-CZLYECHC.js} +20 -9
  5. package/dist/{chunk-YDXBJR74.js → chunk-EWNDBKYK.js} +1 -1
  6. package/dist/{chunk-EUSWEVOA.js → chunk-FAZFADJK.js} +9 -0
  7. package/dist/{chunk-XYCCXKVC.js → chunk-FOY5TF7D.js} +1 -1
  8. package/dist/{chunk-II3X7GLJ.js → chunk-GYCBWGVW.js} +1 -1
  9. package/dist/{chunk-FOEZNEF5.js → chunk-HKHEAH5F.js} +6 -6
  10. package/dist/{chunk-5BFPJWIO.js → chunk-KP4DWTPR.js} +3 -3
  11. package/dist/{chunk-KPP2CFW6.js → chunk-MUTHF2GT.js} +2 -2
  12. package/dist/{chunk-HJSE6SK5.js → chunk-REDDTTGJ.js} +3 -3
  13. package/dist/chunk-TGNS7D4F.js +200 -0
  14. package/dist/collab/rebase.d.ts.map +1 -1
  15. package/dist/collab/rebase.js +4 -2
  16. package/dist/components/editor/index.js +5 -5
  17. package/dist/components/primitives/index.js +6 -6
  18. package/dist/components/sections/brand-guide.js +6 -6
  19. package/dist/components/sections/register-schemas.js +9 -9
  20. package/dist/components/sections/register.js +9 -9
  21. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  22. package/dist/hooks/useEditorPersistence.d.ts +7 -0
  23. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  24. package/dist/hooks/useEditorPublish.d.ts +6 -1
  25. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  26. package/dist/index.js +16 -12
  27. package/dist/lib/block-move.d.ts.map +1 -1
  28. package/dist/lib/dexie.d.ts.map +1 -1
  29. package/dist/lib/dexie.js +6 -1
  30. package/dist/lib/index-ops.d.ts +139 -2
  31. package/dist/lib/index-ops.d.ts.map +1 -1
  32. package/dist/lib/index-ops.js +189 -9
  33. package/dist/lib/index.js +5 -5
  34. package/dist/lib/loader.d.ts +6 -0
  35. package/dist/lib/loader.d.ts.map +1 -1
  36. package/dist/lib/pages.d.ts +18 -0
  37. package/dist/lib/pages.d.ts.map +1 -1
  38. package/dist/media/index.js +3 -3
  39. package/dist/media/provider.d.ts +0 -1
  40. package/dist/media/provider.d.ts.map +1 -1
  41. package/dist/schemas/index.js +5 -3
  42. package/dist/schemas/site-config.d.ts +1 -0
  43. package/dist/schemas/site-config.d.ts.map +1 -1
  44. package/dist/storage/index.d.ts +1 -1
  45. package/dist/storage/index.d.ts.map +1 -1
  46. package/dist/storage/index.js +3 -1
  47. package/dist/storage/types.d.ts +22 -5
  48. package/dist/storage/types.d.ts.map +1 -1
  49. package/dist/types/database.d.ts +14 -3
  50. package/dist/types/database.d.ts.map +1 -1
  51. package/package.json +1 -1
  52. package/src/collab/rebase.ts +15 -0
  53. package/src/components/shell/EditorShell.tsx +70 -11
  54. package/src/hooks/useEditorPersistence.ts +14 -0
  55. package/src/hooks/useEditorPublish.ts +17 -3
  56. package/src/lib/block-move.ts +15 -4
  57. package/src/lib/dexie.ts +6 -1
  58. package/src/lib/index-ops.ts +277 -7
  59. package/src/lib/loader.ts +32 -11
  60. package/src/lib/pages.ts +48 -0
  61. package/src/media/provider.ts +0 -1
  62. package/src/schemas/nav.ts +3 -3
  63. package/src/schemas/site-config.ts +3 -1
  64. package/src/storage/index.ts +1 -1
  65. package/src/storage/types.ts +25 -5
  66. package/src/types/database.ts +14 -3
  67. package/dist/chunk-ZD6XGRQM.js +0 -85
@@ -46,11 +46,18 @@ export interface StorageProvider {
46
46
  * OPTIONAL: providers that cannot search history omit it, and callers fall
47
47
  * back to surfacing the plain conflict.
48
48
  *
49
- * Best-effort by contract. It searches a BOUNDED window, so an old key reads
50
- * as absent, and an implementation may answer "not found" when the history
51
- * read itself fails — failing closed keeps the conflict rather than inventing
52
- * a replay. So `null` means "could not confirm", NOT "your write did not
53
- * land": a caller must not tell the user the earlier attempt failed.
49
+ * `null` means "searched, and this key is not in the window" — which still is
50
+ * NOT proof the write did not land, because the window is BOUNDED and an old
51
+ * key reads as absent. A caller must not tell the user the earlier attempt
52
+ * failed.
53
+ *
54
+ * A failure of the history read itself MUST throw
55
+ * {@link IdempotencyLookupUnavailableError} rather than answer `null`. The two
56
+ * are not interchangeable: a caller deciding whether it is safe to APPLY a
57
+ * write reads `null` as "nothing landed, go ahead", so collapsing a failed
58
+ * read into it turns at-most-once into at-least-once. Callers that are merely
59
+ * REPORTING on a key (or choosing between replay and conflict) can catch it
60
+ * and fall back to the pessimistic answer.
54
61
  */
55
62
  findCommitByIdempotencyKey?(
56
63
  key: string,
@@ -58,6 +65,19 @@ export interface StorageProvider {
58
65
  ): Promise<string | null>;
59
66
  }
60
67
 
68
+ /**
69
+ * The idempotency history read failed, so whether the key landed is UNKNOWN.
70
+ *
71
+ * Distinct from a `null` answer, which means the provider successfully searched
72
+ * and did not find it. See {@link StorageProvider.findCommitByIdempotencyKey}.
73
+ */
74
+ export class IdempotencyLookupUnavailableError extends Error {
75
+ constructor(override readonly cause?: unknown) {
76
+ super("Could not search draft history for the idempotency key");
77
+ this.name = "IdempotencyLookupUnavailableError";
78
+ }
79
+ }
80
+
61
81
  /**
62
82
  * Commit-message trailer carrying a write's idempotency key. The commit itself is
63
83
  * the store — no table, and no TTL to tune: keys live exactly as long as the
@@ -384,7 +384,6 @@ export type Database = {
384
384
  client_id: string
385
385
  client_id_issued_at: number | null
386
386
  client_metadata: Json
387
- client_secret_hash: string | null
388
387
  created_at: string
389
388
  redirect_uris: string[]
390
389
  }
@@ -392,7 +391,6 @@ export type Database = {
392
391
  client_id: string
393
392
  client_id_issued_at?: number | null
394
393
  client_metadata?: Json
395
- client_secret_hash?: string | null
396
394
  created_at?: string
397
395
  redirect_uris: string[]
398
396
  }
@@ -400,7 +398,6 @@ export type Database = {
400
398
  client_id?: string
401
399
  client_id_issued_at?: number | null
402
400
  client_metadata?: Json
403
- client_secret_hash?: string | null
404
401
  created_at?: string
405
402
  redirect_uris?: string[]
406
403
  }
@@ -762,6 +759,20 @@ export type Database = {
762
759
  retry_after_ms: number
763
760
  }[]
764
761
  }
762
+ oauth_rotate_refresh_token: {
763
+ Args: {
764
+ p_expected_client_id: string
765
+ p_next_expires_at: string
766
+ p_next_token_hash: string
767
+ p_token_hash: string
768
+ }
769
+ Returns: {
770
+ status: string
771
+ family_id: string | null
772
+ client_id: string | null
773
+ platform_user_id: string | null
774
+ }[]
775
+ }
765
776
  provision_claim: { Args: { p_site_id: string }; Returns: boolean }
766
777
  rate_limit_cleanup: { Args: { p_max_age_ms: number }; Returns: undefined }
767
778
  rate_limit_hit: {
@@ -1,85 +0,0 @@
1
- // src/lib/nav-tree.ts
2
- function reconcileNav(entries, pages) {
3
- const entryList = Array.isArray(entries) ? entries : [];
4
- const pageList = Array.isArray(pages) ? pages : [];
5
- const validIds = /* @__PURE__ */ new Set();
6
- for (const p of pageList) {
7
- if (p?.id) validIds.add(p.id);
8
- }
9
- const placed = /* @__PURE__ */ new Set();
10
- const seenGroupIds = /* @__PURE__ */ new Set();
11
- const result = [];
12
- for (const entry of entryList) {
13
- if (entry?.kind === "page") {
14
- if (!validIds.has(entry.pageId) || placed.has(entry.pageId)) continue;
15
- placed.add(entry.pageId);
16
- result.push({ ...entry });
17
- continue;
18
- }
19
- if (entry?.kind !== "group") continue;
20
- if (seenGroupIds.has(entry.id)) continue;
21
- seenGroupIds.add(entry.id);
22
- const claimed = Array.isArray(entry.pageIds) ? entry.pageIds : [];
23
- const pageIds = claimed.filter((id) => {
24
- if (!validIds.has(id) || placed.has(id)) return false;
25
- placed.add(id);
26
- return true;
27
- });
28
- const group = { ...entry, pageIds };
29
- result.push(group);
30
- }
31
- for (const p of pageList) {
32
- if (!p?.id || placed.has(p.id)) continue;
33
- placed.add(p.id);
34
- result.push({ kind: "page", pageId: p.id });
35
- }
36
- return result;
37
- }
38
- function navEntries(index) {
39
- return reconcileNav(index.nav ?? [], index.pages);
40
- }
41
- function pagesInNavOrder(index) {
42
- const byId = new Map(index.pages.map((p) => [p.id, p]));
43
- const out = [];
44
- for (const entry of navEntries(index)) {
45
- if (entry.kind === "page") {
46
- const p = byId.get(entry.pageId);
47
- if (p) out.push(p);
48
- } else {
49
- for (const id of entry.pageIds) {
50
- const p = byId.get(id);
51
- if (p) out.push(p);
52
- }
53
- }
54
- }
55
- return out;
56
- }
57
- function groupOfPage(index, pageId) {
58
- for (const entry of navEntries(index)) {
59
- if (entry.kind === "group" && entry.pageIds.includes(pageId)) return entry;
60
- }
61
- return null;
62
- }
63
- function groupDisplayLabel(label) {
64
- return label || "Untitled group";
65
- }
66
-
67
- // src/lib/pages.ts
68
- function slugifyPageSlug(input) {
69
- return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
70
- }
71
- function audiencePasses(access, audience) {
72
- if (access.length === 0) return true;
73
- if (!audience) return true;
74
- return access.includes(audience);
75
- }
76
-
77
- export {
78
- reconcileNav,
79
- navEntries,
80
- pagesInNavOrder,
81
- groupOfPage,
82
- groupDisplayLabel,
83
- slugifyPageSlug,
84
- audiencePasses
85
- };