@siteping/widget 0.10.10 → 0.11.1
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/README.md +5 -4
- package/dist/chunk-26577FDQ.js +9 -0
- package/dist/chunk-26577FDQ.js.map +1 -0
- package/dist/chunk-3EHIWTJH.js +9 -0
- package/dist/chunk-3EHIWTJH.js.map +1 -0
- package/dist/chunk-6MCFOKVG.cjs +9 -0
- package/dist/chunk-6MCFOKVG.cjs.map +1 -0
- package/dist/chunk-Q34GDCKE.cjs +9 -0
- package/dist/chunk-Q34GDCKE.cjs.map +1 -0
- package/dist/concurrency.d.cts +14 -0
- package/dist/concurrency.d.ts +14 -0
- package/dist/de-73CTH2E4.cjs +2 -0
- package/dist/de-73CTH2E4.cjs.map +1 -0
- package/dist/de-GUUJUHYP.js +2 -0
- package/dist/de-GUUJUHYP.js.map +1 -0
- package/dist/deep-link.d.cts +14 -0
- package/dist/deep-link.d.ts +14 -0
- package/dist/email.d.cts +6 -3
- package/dist/email.d.ts +6 -3
- package/dist/errors.d.cts +18 -4
- package/dist/errors.d.ts +18 -4
- package/dist/{es-HEVFJPRI.js → es-3MXMSDUC.js} +2 -2
- package/dist/es-3MXMSDUC.js.map +1 -0
- package/dist/{es-5XQA3TPT.cjs → es-WJZ3XARH.cjs} +2 -2
- package/dist/es-WJZ3XARH.cjs.map +1 -0
- package/dist/filters.d.cts +31 -7
- package/dist/filters.d.ts +31 -7
- package/dist/fr-52F3ZCLQ.js +2 -0
- package/dist/fr-52F3ZCLQ.js.map +1 -0
- package/dist/fr-ZCRIJWI3.cjs +2 -0
- package/dist/fr-ZCRIJWI3.cjs.map +1 -0
- package/dist/i18n.d.cts +18 -0
- package/dist/i18n.d.ts +18 -0
- package/dist/index.cjs +3 -1588
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.global.js +4 -3389
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +3 -1588
- package/dist/index.js.map +1 -1
- package/dist/it-MEUT3RCC.js +2 -0
- package/dist/it-MEUT3RCC.js.map +1 -0
- package/dist/it-TGUTW6MO.cjs +2 -0
- package/dist/it-TGUTW6MO.cjs.map +1 -0
- package/dist/ja-DOS7AWLW.cjs +2 -0
- package/dist/ja-DOS7AWLW.cjs.map +1 -0
- package/dist/ja-U7NRNGPQ.js +2 -0
- package/dist/ja-U7NRNGPQ.js.map +1 -0
- package/dist/ko-U2CS6XQ4.js +2 -0
- package/dist/ko-U2CS6XQ4.js.map +1 -0
- package/dist/ko-ZUL567LW.cjs +2 -0
- package/dist/ko-ZUL567LW.cjs.map +1 -0
- package/dist/panel-3BEMZFIR.cjs +2 -0
- package/dist/panel-3BEMZFIR.cjs.map +1 -0
- package/dist/panel-HPDIAYLQ.js +2 -0
- package/dist/panel-HPDIAYLQ.js.map +1 -0
- package/dist/panel-MIWFGD7X.cjs +2 -0
- package/dist/panel-MIWFGD7X.cjs.map +1 -0
- package/dist/panel-XTNU6XHV.js +2 -0
- package/dist/panel-XTNU6XHV.js.map +1 -0
- package/dist/pt-BZRBHCYN.cjs +2 -0
- package/dist/pt-BZRBHCYN.cjs.map +1 -0
- package/dist/pt-MOS5DVOG.js +2 -0
- package/dist/pt-MOS5DVOG.js.map +1 -0
- package/dist/react.cjs +3 -1588
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +3 -1588
- package/dist/react.js.map +1 -1
- package/dist/ru-KDNRHHNZ.cjs +2 -0
- package/dist/ru-KDNRHHNZ.cjs.map +1 -0
- package/dist/ru-VSWB5NKK.js +2 -0
- package/dist/ru-VSWB5NKK.js.map +1 -0
- package/dist/schema.d.cts +54 -0
- package/dist/schema.d.ts +54 -0
- package/dist/screenshot-storage.d.cts +61 -19
- package/dist/screenshot-storage.d.ts +61 -19
- package/dist/siteping-core.d.cts +9 -6
- package/dist/siteping-core.d.ts +9 -6
- package/dist/store-helpers.d.cts +59 -15
- package/dist/store-helpers.d.ts +59 -15
- package/dist/type-utils.d.cts +8 -0
- package/dist/type-utils.d.ts +8 -0
- package/dist/types.d.cts +399 -33
- package/dist/types.d.ts +399 -33
- package/dist/wire.d.cts +35 -2
- package/dist/wire.d.ts +35 -2
- package/package.json +5 -3
- package/dist/chunk-AFLWWD6M.cjs +0 -1796
- package/dist/chunk-AFLWWD6M.cjs.map +0 -1
- package/dist/chunk-ATTI2TS4.js +0 -1796
- package/dist/chunk-ATTI2TS4.js.map +0 -1
- package/dist/chunk-BP5TH2CD.js +0 -1796
- package/dist/chunk-BP5TH2CD.js.map +0 -1
- package/dist/chunk-OSADAHGS.cjs +0 -1796
- package/dist/chunk-OSADAHGS.cjs.map +0 -1
- package/dist/de-AZUOIGF2.cjs +0 -2
- package/dist/de-AZUOIGF2.cjs.map +0 -1
- package/dist/de-MAGIJBFC.js +0 -2
- package/dist/de-MAGIJBFC.js.map +0 -1
- package/dist/es-5XQA3TPT.cjs.map +0 -1
- package/dist/es-HEVFJPRI.js.map +0 -1
- package/dist/fr-ERYSAH32.cjs +0 -2
- package/dist/fr-ERYSAH32.cjs.map +0 -1
- package/dist/fr-OM2PHLDH.js +0 -2
- package/dist/fr-OM2PHLDH.js.map +0 -1
- package/dist/it-NXAZR4K6.cjs +0 -2
- package/dist/it-NXAZR4K6.cjs.map +0 -1
- package/dist/it-OQVYHKKV.js +0 -2
- package/dist/it-OQVYHKKV.js.map +0 -1
- package/dist/panel-2FEECS2N.cjs +0 -2
- package/dist/panel-2FEECS2N.cjs.map +0 -1
- package/dist/panel-CSFFA5FF.cjs +0 -2
- package/dist/panel-CSFFA5FF.cjs.map +0 -1
- package/dist/panel-S2UR5BSD.js +0 -2
- package/dist/panel-S2UR5BSD.js.map +0 -1
- package/dist/panel-SGSUHR7V.js +0 -2
- package/dist/panel-SGSUHR7V.js.map +0 -1
- package/dist/pt-CODDT6VY.cjs +0 -2
- package/dist/pt-CODDT6VY.cjs.map +0 -1
- package/dist/pt-VUUNL42H.js +0 -2
- package/dist/pt-VUUNL42H.js.map +0 -1
- package/dist/ru-72WUEADV.cjs +0 -2
- package/dist/ru-72WUEADV.cjs.map +0 -1
- package/dist/ru-NDWY7Y36.js +0 -2
- package/dist/ru-NDWY7Y36.js.map +0 -1
package/dist/store-helpers.d.cts
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* timestamps), filter/paginate with `applyFeedbackFilters`, and implement
|
|
8
8
|
* the dedup/update/delete choreography of the `SitepingStore` contract.
|
|
9
9
|
*
|
|
10
|
-
* `buildFeedbackRecord` / `buildAnnotationRecord`
|
|
11
|
-
* any adapter. `createCollectionStore` covers all
|
|
12
|
-
* `persist`, and `generateId`, and it returns a fully
|
|
13
|
-
* `SitepingStore` — writing a new snapshot adapter is ~20 lines
|
|
14
|
-
* storage specifics.
|
|
10
|
+
* `buildFeedbackRecord` / `buildAnnotationRecord` / `buildCommentRecord`
|
|
11
|
+
* cover the first part for any adapter. `createCollectionStore` covers all
|
|
12
|
+
* of it: give it `load`, `persist`, and `generateId`, and it returns a fully
|
|
13
|
+
* conformant `SitepingStore` — writing a new snapshot adapter is ~20 lines
|
|
14
|
+
* plus its storage specifics.
|
|
15
15
|
*/
|
|
16
|
-
import type { AnnotationCreateInput, AnnotationRecord, FeedbackCreateInput, FeedbackRecord, SitepingStore } from "./types.cjs";
|
|
16
|
+
import type { AnnotationCreateInput, AnnotationRecord, CommentCreateInput, CommentRecord, FeedbackCreateInput, FeedbackRecord, SitepingStore } from "./types.cjs";
|
|
17
17
|
/**
|
|
18
18
|
* Build a persisted `AnnotationRecord` from its create input — normalizes
|
|
19
19
|
* the optional anchor fields to `null` and stamps identity/timestamp.
|
|
@@ -23,12 +23,20 @@ export declare function buildAnnotationRecord(input: AnnotationCreateInput, ctx:
|
|
|
23
23
|
feedbackId: string;
|
|
24
24
|
now: Date;
|
|
25
25
|
}): AnnotationRecord;
|
|
26
|
+
/** Build a persisted `CommentRecord` from its create input — stamps identity, thread and timestamp. */
|
|
27
|
+
export declare function buildCommentRecord(input: CommentCreateInput, ctx: {
|
|
28
|
+
id: string;
|
|
29
|
+
feedbackId: string;
|
|
30
|
+
now?: Date;
|
|
31
|
+
}): CommentRecord;
|
|
26
32
|
/**
|
|
27
33
|
* Build a persisted `FeedbackRecord` (with its annotations) from a create
|
|
28
34
|
* input — normalizes every optional field to `null` and stamps ids and
|
|
29
35
|
* timestamps. Adapters without external screenshot storage keep the data
|
|
30
36
|
* URL inline on `screenshotUrl`, which is what this helper does; adapters
|
|
31
37
|
* with a `ScreenshotStorage` upload first and override `screenshotUrl`.
|
|
38
|
+
* It leaves `comments` out, so the record minus its `annotations` stays an
|
|
39
|
+
* insertable feedback row; a store with threads returns `comments: []` itself.
|
|
32
40
|
*/
|
|
33
41
|
export declare function buildFeedbackRecord(input: FeedbackCreateInput, ctx: {
|
|
34
42
|
id: string;
|
|
@@ -37,8 +45,11 @@ export declare function buildFeedbackRecord(input: FeedbackCreateInput, ctx: {
|
|
|
37
45
|
}): FeedbackRecord;
|
|
38
46
|
/**
|
|
39
47
|
* Storage primitives behind a collection store. `load`/`persist` may be
|
|
40
|
-
* sync or async
|
|
41
|
-
*
|
|
48
|
+
* sync or async, so in-memory arrays, localStorage and async KV stores all
|
|
49
|
+
* fit the same three functions. When both are sync, a mutation runs from
|
|
50
|
+
* `load` to `persist` without yielding, so no other code in the realm can
|
|
51
|
+
* write in between; an async backend is only serialized against the
|
|
52
|
+
* engine's own queue.
|
|
42
53
|
*/
|
|
43
54
|
export interface CollectionStoreBackend {
|
|
44
55
|
/**
|
|
@@ -55,28 +66,57 @@ export interface CollectionStoreBackend {
|
|
|
55
66
|
* update.
|
|
56
67
|
*/
|
|
57
68
|
persist(feedbacks: FeedbackRecord[]): void | Promise<void>;
|
|
58
|
-
/** Generate a unique id for a new feedback or
|
|
69
|
+
/** Generate a unique id for a new feedback, annotation or comment record. */
|
|
59
70
|
generateId(): string;
|
|
71
|
+
/**
|
|
72
|
+
* Keep discussion threads on the records: the store gains `addComment` and
|
|
73
|
+
* `deleteComment`, and new records start with `comments: []`. Opt in once
|
|
74
|
+
* `load` hands back what `persist` wrote for them, each comment's
|
|
75
|
+
* `createdAt` a `Date` again (a JSON backend revives it like the record's
|
|
76
|
+
* own dates). Off by default, so an adapter written before threads never
|
|
77
|
+
* gains them — over storage never written for them — on an engine update.
|
|
78
|
+
*/
|
|
79
|
+
comments?: boolean | undefined;
|
|
60
80
|
}
|
|
61
81
|
/**
|
|
62
82
|
* A `SitepingStore` with the optional `verifyProjectOwnership` guaranteed —
|
|
63
|
-
* what `createCollectionStore` returns
|
|
83
|
+
* what `createCollectionStore` returns, which also guarantees
|
|
84
|
+
* `createFeedbackIfAbsent`.
|
|
64
85
|
*/
|
|
65
86
|
export type CollectionStore = SitepingStore & Required<Pick<SitepingStore, "verifyProjectOwnership">>;
|
|
66
87
|
/**
|
|
67
88
|
* Build a fully conformant `SitepingStore` on top of a snapshot backend.
|
|
68
89
|
*
|
|
69
90
|
* The engine implements the whole store contract: clientId dedup (idempotent
|
|
70
|
-
* create), newest-first
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
91
|
+
* create, with `createFeedbackIfAbsent` reporting inserts), newest-first
|
|
92
|
+
* ordering, the standard filter/pagination pipeline, `StoreNotFoundError` on
|
|
93
|
+
* missing update/delete, project-scoped bulk delete,
|
|
94
|
+
* `verifyProjectOwnership`, and — with `comments: true` — discussion threads
|
|
95
|
+
* (`addComment`, `deleteComment`) kept on each record. The snapshot returned by `load` is
|
|
96
|
+
* never mutated: every write hands `persist` a new array, so a failed write leaves
|
|
74
97
|
* a cached snapshot exactly as it was. When `persist` fails during `createFeedback`
|
|
75
98
|
* and the record carries an inline screenshot, the engine retries once
|
|
76
99
|
* without the screenshot (by far the heaviest field) so the text feedback
|
|
77
100
|
* survives a storage-quota hit; if that also fails, the error propagates —
|
|
78
101
|
* returning the record would claim a success that was never persisted.
|
|
79
102
|
*
|
|
103
|
+
* Mutations (`createFeedbackIfAbsent`, `createFeedback`, `updateFeedback`,
|
|
104
|
+
* `deleteFeedback`, `deleteAllFeedbacks`, `addComment`, `deleteComment`) run
|
|
105
|
+
* one at a time through a queue owned by the returned store, so concurrent
|
|
106
|
+
* calls — the widget's `Promise.all` bulk resolve/delete, a comment posted
|
|
107
|
+
* while its feedback is resolved — never start from the same snapshot and
|
|
108
|
+
* overwrite each other, and `createFeedbackIfAbsent` reports `created: true`
|
|
109
|
+
* exactly once per `clientId`. A failed mutation rejects with its own error
|
|
110
|
+
* and does not block the ones queued after it, but `load` and `persist` must
|
|
111
|
+
* always settle: one that never does stalls every later mutation on the
|
|
112
|
+
* store, so give network-backed primitives a timeout. Reads are not queued: they see the
|
|
113
|
+
* last persisted snapshot. The guarantee is scoped to one store instance in
|
|
114
|
+
* one JS realm — two instances over the same storage (two
|
|
115
|
+
* `LocalStorageStore`s on one key, two browser tabs, several server
|
|
116
|
+
* processes sharing a KV or a file) are not coordinated; a backend that
|
|
117
|
+
* needs that must bring its own atomic primitive (a transaction, a
|
|
118
|
+
* compare-and-set).
|
|
119
|
+
*
|
|
80
120
|
* @example
|
|
81
121
|
* ```ts
|
|
82
122
|
* export class MemoryStore implements SitepingStore {
|
|
@@ -87,10 +127,14 @@ export type CollectionStore = SitepingStore & Required<Pick<SitepingStore, "veri
|
|
|
87
127
|
* this.feedbacks = next;
|
|
88
128
|
* },
|
|
89
129
|
* generateId: () => crypto.randomUUID(),
|
|
130
|
+
* comments: true,
|
|
90
131
|
* });
|
|
91
132
|
* createFeedback = this.store.createFeedback;
|
|
92
133
|
* // …delegate the remaining methods the same way
|
|
93
134
|
* }
|
|
94
135
|
* ```
|
|
95
136
|
*/
|
|
96
|
-
export declare function createCollectionStore(backend: CollectionStoreBackend
|
|
137
|
+
export declare function createCollectionStore(backend: CollectionStoreBackend & {
|
|
138
|
+
comments: true;
|
|
139
|
+
}): CollectionStore & Required<Pick<SitepingStore, "createFeedbackIfAbsent" | "addComment" | "deleteComment">>;
|
|
140
|
+
export declare function createCollectionStore(backend: CollectionStoreBackend): CollectionStore & Required<Pick<SitepingStore, "createFeedbackIfAbsent">>;
|
package/dist/store-helpers.d.ts
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* timestamps), filter/paginate with `applyFeedbackFilters`, and implement
|
|
8
8
|
* the dedup/update/delete choreography of the `SitepingStore` contract.
|
|
9
9
|
*
|
|
10
|
-
* `buildFeedbackRecord` / `buildAnnotationRecord`
|
|
11
|
-
* any adapter. `createCollectionStore` covers all
|
|
12
|
-
* `persist`, and `generateId`, and it returns a fully
|
|
13
|
-
* `SitepingStore` — writing a new snapshot adapter is ~20 lines
|
|
14
|
-
* storage specifics.
|
|
10
|
+
* `buildFeedbackRecord` / `buildAnnotationRecord` / `buildCommentRecord`
|
|
11
|
+
* cover the first part for any adapter. `createCollectionStore` covers all
|
|
12
|
+
* of it: give it `load`, `persist`, and `generateId`, and it returns a fully
|
|
13
|
+
* conformant `SitepingStore` — writing a new snapshot adapter is ~20 lines
|
|
14
|
+
* plus its storage specifics.
|
|
15
15
|
*/
|
|
16
|
-
import type { AnnotationCreateInput, AnnotationRecord, FeedbackCreateInput, FeedbackRecord, SitepingStore } from "./types.js";
|
|
16
|
+
import type { AnnotationCreateInput, AnnotationRecord, CommentCreateInput, CommentRecord, FeedbackCreateInput, FeedbackRecord, SitepingStore } from "./types.js";
|
|
17
17
|
/**
|
|
18
18
|
* Build a persisted `AnnotationRecord` from its create input — normalizes
|
|
19
19
|
* the optional anchor fields to `null` and stamps identity/timestamp.
|
|
@@ -23,12 +23,20 @@ export declare function buildAnnotationRecord(input: AnnotationCreateInput, ctx:
|
|
|
23
23
|
feedbackId: string;
|
|
24
24
|
now: Date;
|
|
25
25
|
}): AnnotationRecord;
|
|
26
|
+
/** Build a persisted `CommentRecord` from its create input — stamps identity, thread and timestamp. */
|
|
27
|
+
export declare function buildCommentRecord(input: CommentCreateInput, ctx: {
|
|
28
|
+
id: string;
|
|
29
|
+
feedbackId: string;
|
|
30
|
+
now?: Date;
|
|
31
|
+
}): CommentRecord;
|
|
26
32
|
/**
|
|
27
33
|
* Build a persisted `FeedbackRecord` (with its annotations) from a create
|
|
28
34
|
* input — normalizes every optional field to `null` and stamps ids and
|
|
29
35
|
* timestamps. Adapters without external screenshot storage keep the data
|
|
30
36
|
* URL inline on `screenshotUrl`, which is what this helper does; adapters
|
|
31
37
|
* with a `ScreenshotStorage` upload first and override `screenshotUrl`.
|
|
38
|
+
* It leaves `comments` out, so the record minus its `annotations` stays an
|
|
39
|
+
* insertable feedback row; a store with threads returns `comments: []` itself.
|
|
32
40
|
*/
|
|
33
41
|
export declare function buildFeedbackRecord(input: FeedbackCreateInput, ctx: {
|
|
34
42
|
id: string;
|
|
@@ -37,8 +45,11 @@ export declare function buildFeedbackRecord(input: FeedbackCreateInput, ctx: {
|
|
|
37
45
|
}): FeedbackRecord;
|
|
38
46
|
/**
|
|
39
47
|
* Storage primitives behind a collection store. `load`/`persist` may be
|
|
40
|
-
* sync or async
|
|
41
|
-
*
|
|
48
|
+
* sync or async, so in-memory arrays, localStorage and async KV stores all
|
|
49
|
+
* fit the same three functions. When both are sync, a mutation runs from
|
|
50
|
+
* `load` to `persist` without yielding, so no other code in the realm can
|
|
51
|
+
* write in between; an async backend is only serialized against the
|
|
52
|
+
* engine's own queue.
|
|
42
53
|
*/
|
|
43
54
|
export interface CollectionStoreBackend {
|
|
44
55
|
/**
|
|
@@ -55,28 +66,57 @@ export interface CollectionStoreBackend {
|
|
|
55
66
|
* update.
|
|
56
67
|
*/
|
|
57
68
|
persist(feedbacks: FeedbackRecord[]): void | Promise<void>;
|
|
58
|
-
/** Generate a unique id for a new feedback or
|
|
69
|
+
/** Generate a unique id for a new feedback, annotation or comment record. */
|
|
59
70
|
generateId(): string;
|
|
71
|
+
/**
|
|
72
|
+
* Keep discussion threads on the records: the store gains `addComment` and
|
|
73
|
+
* `deleteComment`, and new records start with `comments: []`. Opt in once
|
|
74
|
+
* `load` hands back what `persist` wrote for them, each comment's
|
|
75
|
+
* `createdAt` a `Date` again (a JSON backend revives it like the record's
|
|
76
|
+
* own dates). Off by default, so an adapter written before threads never
|
|
77
|
+
* gains them — over storage never written for them — on an engine update.
|
|
78
|
+
*/
|
|
79
|
+
comments?: boolean | undefined;
|
|
60
80
|
}
|
|
61
81
|
/**
|
|
62
82
|
* A `SitepingStore` with the optional `verifyProjectOwnership` guaranteed —
|
|
63
|
-
* what `createCollectionStore` returns
|
|
83
|
+
* what `createCollectionStore` returns, which also guarantees
|
|
84
|
+
* `createFeedbackIfAbsent`.
|
|
64
85
|
*/
|
|
65
86
|
export type CollectionStore = SitepingStore & Required<Pick<SitepingStore, "verifyProjectOwnership">>;
|
|
66
87
|
/**
|
|
67
88
|
* Build a fully conformant `SitepingStore` on top of a snapshot backend.
|
|
68
89
|
*
|
|
69
90
|
* The engine implements the whole store contract: clientId dedup (idempotent
|
|
70
|
-
* create), newest-first
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
91
|
+
* create, with `createFeedbackIfAbsent` reporting inserts), newest-first
|
|
92
|
+
* ordering, the standard filter/pagination pipeline, `StoreNotFoundError` on
|
|
93
|
+
* missing update/delete, project-scoped bulk delete,
|
|
94
|
+
* `verifyProjectOwnership`, and — with `comments: true` — discussion threads
|
|
95
|
+
* (`addComment`, `deleteComment`) kept on each record. The snapshot returned by `load` is
|
|
96
|
+
* never mutated: every write hands `persist` a new array, so a failed write leaves
|
|
74
97
|
* a cached snapshot exactly as it was. When `persist` fails during `createFeedback`
|
|
75
98
|
* and the record carries an inline screenshot, the engine retries once
|
|
76
99
|
* without the screenshot (by far the heaviest field) so the text feedback
|
|
77
100
|
* survives a storage-quota hit; if that also fails, the error propagates —
|
|
78
101
|
* returning the record would claim a success that was never persisted.
|
|
79
102
|
*
|
|
103
|
+
* Mutations (`createFeedbackIfAbsent`, `createFeedback`, `updateFeedback`,
|
|
104
|
+
* `deleteFeedback`, `deleteAllFeedbacks`, `addComment`, `deleteComment`) run
|
|
105
|
+
* one at a time through a queue owned by the returned store, so concurrent
|
|
106
|
+
* calls — the widget's `Promise.all` bulk resolve/delete, a comment posted
|
|
107
|
+
* while its feedback is resolved — never start from the same snapshot and
|
|
108
|
+
* overwrite each other, and `createFeedbackIfAbsent` reports `created: true`
|
|
109
|
+
* exactly once per `clientId`. A failed mutation rejects with its own error
|
|
110
|
+
* and does not block the ones queued after it, but `load` and `persist` must
|
|
111
|
+
* always settle: one that never does stalls every later mutation on the
|
|
112
|
+
* store, so give network-backed primitives a timeout. Reads are not queued: they see the
|
|
113
|
+
* last persisted snapshot. The guarantee is scoped to one store instance in
|
|
114
|
+
* one JS realm — two instances over the same storage (two
|
|
115
|
+
* `LocalStorageStore`s on one key, two browser tabs, several server
|
|
116
|
+
* processes sharing a KV or a file) are not coordinated; a backend that
|
|
117
|
+
* needs that must bring its own atomic primitive (a transaction, a
|
|
118
|
+
* compare-and-set).
|
|
119
|
+
*
|
|
80
120
|
* @example
|
|
81
121
|
* ```ts
|
|
82
122
|
* export class MemoryStore implements SitepingStore {
|
|
@@ -87,10 +127,14 @@ export type CollectionStore = SitepingStore & Required<Pick<SitepingStore, "veri
|
|
|
87
127
|
* this.feedbacks = next;
|
|
88
128
|
* },
|
|
89
129
|
* generateId: () => crypto.randomUUID(),
|
|
130
|
+
* comments: true,
|
|
90
131
|
* });
|
|
91
132
|
* createFeedback = this.store.createFeedback;
|
|
92
133
|
* // …delegate the remaining methods the same way
|
|
93
134
|
* }
|
|
94
135
|
* ```
|
|
95
136
|
*/
|
|
96
|
-
export declare function createCollectionStore(backend: CollectionStoreBackend
|
|
137
|
+
export declare function createCollectionStore(backend: CollectionStoreBackend & {
|
|
138
|
+
comments: true;
|
|
139
|
+
}): CollectionStore & Required<Pick<SitepingStore, "createFeedbackIfAbsent" | "addComment" | "deleteComment">>;
|
|
140
|
+
export declare function createCollectionStore(backend: CollectionStoreBackend): CollectionStore & Required<Pick<SitepingStore, "createFeedbackIfAbsent">>;
|
package/dist/type-utils.d.cts
CHANGED
|
@@ -41,6 +41,14 @@ export type AssertEqual<Actual, Expected> = IfEquals<Actual, Expected, true, nev
|
|
|
41
41
|
export type Serialized<T> = {
|
|
42
42
|
[K in keyof T]: T[K] extends Date ? string : T[K] extends Date | null ? string | null : T[K] extends (infer U)[] ? Serialized<U>[] : T[K];
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Read-only all the way down, for plain data that is deeply frozen at
|
|
46
|
+
* runtime: nested objects get read-only properties, arrays become
|
|
47
|
+
* `readonly` arrays.
|
|
48
|
+
*/
|
|
49
|
+
export type DeepReadonly<T> = T extends readonly (infer U)[] ? readonly DeepReadonly<U>[] : T extends object ? {
|
|
50
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
51
|
+
} : T;
|
|
44
52
|
/**
|
|
45
53
|
* Type guard that narrows `value` to a non-null `Record<PropertyKey, unknown>`.
|
|
46
54
|
* Useful when validating arbitrary inputs before reading fields.
|
package/dist/type-utils.d.ts
CHANGED
|
@@ -41,6 +41,14 @@ export type AssertEqual<Actual, Expected> = IfEquals<Actual, Expected, true, nev
|
|
|
41
41
|
export type Serialized<T> = {
|
|
42
42
|
[K in keyof T]: T[K] extends Date ? string : T[K] extends Date | null ? string | null : T[K] extends (infer U)[] ? Serialized<U>[] : T[K];
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Read-only all the way down, for plain data that is deeply frozen at
|
|
46
|
+
* runtime: nested objects get read-only properties, arrays become
|
|
47
|
+
* `readonly` arrays.
|
|
48
|
+
*/
|
|
49
|
+
export type DeepReadonly<T> = T extends readonly (infer U)[] ? readonly DeepReadonly<U>[] : T extends object ? {
|
|
50
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
51
|
+
} : T;
|
|
44
52
|
/**
|
|
45
53
|
* Type guard that narrows `value` to a non-null `Record<PropertyKey, unknown>`.
|
|
46
54
|
* Useful when validating arbitrary inputs before reading fields.
|