@siteping/widget 0.10.6 → 0.10.8
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/dist/chunk-4CK3N4YE.js +1796 -0
- package/dist/chunk-4CK3N4YE.js.map +1 -0
- package/dist/chunk-BJFC7TVL.cjs +1796 -0
- package/dist/chunk-BJFC7TVL.cjs.map +1 -0
- package/dist/chunk-EYISG4OI.js +1796 -0
- package/dist/chunk-EYISG4OI.js.map +1 -0
- package/dist/chunk-OK2KX3KN.cjs +1796 -0
- package/dist/chunk-OK2KX3KN.cjs.map +1 -0
- package/dist/email.d.cts +19 -0
- package/dist/email.d.ts +19 -0
- package/dist/filters.d.cts +29 -4
- package/dist/filters.d.ts +29 -4
- package/dist/i18n.d.cts +67 -0
- package/dist/i18n.d.ts +67 -0
- package/dist/index.cjs +50 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +152 -6
- package/dist/index.d.ts +152 -6
- package/dist/index.global.js +74 -74
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +50 -50
- package/dist/index.js.map +1 -1
- package/dist/panel-KCYUMYAI.cjs +2 -0
- package/dist/panel-KCYUMYAI.cjs.map +1 -0
- package/dist/panel-KV2AQHC2.js +2 -0
- package/dist/panel-KV2AQHC2.js.map +1 -0
- package/dist/panel-LYS3425X.cjs +2 -0
- package/dist/panel-LYS3425X.cjs.map +1 -0
- package/dist/panel-W2LHYGFS.js +2 -0
- package/dist/panel-W2LHYGFS.js.map +1 -0
- package/dist/react.cjs +50 -50
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +49 -49
- package/dist/react.js.map +1 -1
- package/dist/screenshot-storage.d.cts +5 -0
- package/dist/screenshot-storage.d.ts +5 -0
- package/dist/siteping-core.d.cts +11 -5
- package/dist/siteping-core.d.ts +11 -5
- package/dist/store-helpers.d.cts +96 -0
- package/dist/store-helpers.d.ts +96 -0
- package/dist/type-utils.d.cts +13 -44
- package/dist/type-utils.d.ts +13 -44
- package/dist/types.d.cts +149 -112
- package/dist/types.d.ts +149 -112
- package/dist/wire.d.cts +35 -0
- package/dist/wire.d.ts +35 -0
- package/package.json +4 -3
- package/dist/chunk-D2AVRF24.js +0 -1796
- package/dist/chunk-D2AVRF24.js.map +0 -1
- package/dist/chunk-GRKBXAGP.cjs +0 -1796
- package/dist/chunk-GRKBXAGP.cjs.map +0 -1
- package/dist/panel-LMVRKAQH.cjs +0 -2
- package/dist/panel-LMVRKAQH.cjs.map +0 -1
- package/dist/panel-OXUE7PJY.js +0 -2
- package/dist/panel-OXUE7PJY.js.map +0 -1
|
@@ -40,6 +40,11 @@ export interface ScreenshotStorage {
|
|
|
40
40
|
*
|
|
41
41
|
* Adapters call this synchronously inside `createFeedback` — keep it
|
|
42
42
|
* fast or move to a queue if needed.
|
|
43
|
+
*
|
|
44
|
+
* **Security note:** `ctx.feedbackId` is the *client-generated* id
|
|
45
|
+
* (`clientId`) — the record id does not exist yet at upload time. Treat it
|
|
46
|
+
* as attacker-controlled: sanitize before using it in filesystem paths or
|
|
47
|
+
* object keys, even though server adapters validate its shape upstream.
|
|
43
48
|
*/
|
|
44
49
|
upload(dataUrl: string, ctx: {
|
|
45
50
|
feedbackId: string;
|
|
@@ -40,6 +40,11 @@ export interface ScreenshotStorage {
|
|
|
40
40
|
*
|
|
41
41
|
* Adapters call this synchronously inside `createFeedback` — keep it
|
|
42
42
|
* fast or move to a queue if needed.
|
|
43
|
+
*
|
|
44
|
+
* **Security note:** `ctx.feedbackId` is the *client-generated* id
|
|
45
|
+
* (`clientId`) — the record id does not exist yet at upload time. Treat it
|
|
46
|
+
* as attacker-controlled: sanitize before using it in filesystem paths or
|
|
47
|
+
* object keys, even though server adapters validate its shape upstream.
|
|
43
48
|
*/
|
|
44
49
|
upload(dataUrl: string, ctx: {
|
|
45
50
|
feedbackId: string;
|
package/dist/siteping-core.d.cts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
export { EMAIL_PATTERN, isValidEmail } from "./email.cjs";
|
|
1
2
|
export type { SitepingErrorCode } from "./errors.cjs";
|
|
2
3
|
export { SitepingAuthError, SitepingError, SitepingNetworkError, SitepingValidationError } from "./errors.cjs";
|
|
3
|
-
export type { FilterResult } from "./filters.cjs";
|
|
4
|
-
export { applyFeedbackFilters } from "./filters.cjs";
|
|
4
|
+
export type { FilterResult, Pagination } from "./filters.cjs";
|
|
5
|
+
export { applyFeedbackFilters, clampPagination, DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT } from "./filters.cjs";
|
|
6
|
+
export type { I18n, LocaleLoaders, TranslateFunction } from "./i18n.cjs";
|
|
7
|
+
export { createI18n, interpolate, tWithParams } from "./i18n.cjs";
|
|
5
8
|
export type { FieldDef, IndexDef, ModelDef, PrismaNativeType, PrismaScalarType, RelationDef, RelationKind, RelationOnDelete, SitepingModelFieldName, SitepingModelName, } from "./schema.cjs";
|
|
6
9
|
export { isRelationField, isScalarField, SITEPING_MODELS } from "./schema.cjs";
|
|
7
10
|
export type { ScreenshotStorage } from "./screenshot-storage.cjs";
|
|
8
|
-
export type {
|
|
11
|
+
export type { CollectionStore, CollectionStoreBackend } from "./store-helpers.cjs";
|
|
12
|
+
export { buildAnnotationRecord, buildFeedbackRecord, createCollectionStore } from "./store-helpers.cjs";
|
|
13
|
+
export type { AssertEqual, IfEquals, Prettify, Serialized } from "./type-utils.cjs";
|
|
9
14
|
export { hasOwn, isRecord } from "./type-utils.cjs";
|
|
10
|
-
export type { AnchorData, AnnotationCreateInput, AnnotationPayload, AnnotationRecord, AnnotationResponse, BuiltinLocale, ConsoleDiagnosticEntry, ConsoleDiagnosticLevel, DiagnosticsCaptureOptions, DiagnosticsSnapshot, FeedbackCreateInput, FeedbackPage, FeedbackPayload, FeedbackQuery, FeedbackRecord, FeedbackResponse, FeedbackResponseList, FeedbackStatus, FeedbackType, FeedbackUpdateInput, NetworkDiagnosticEntry, PageScope, RectData, ScreenshotRegion, SitepingConfig, SitepingDeepLinkOptions, SitepingHeadersOption, SitepingIdentity, SitepingInstance, SitepingLocale, SitepingPosition, SitepingPublicEventListener, SitepingPublicEvents, SitepingSkipReason, SitepingStore, SitepingTheme, SitepingUnsubscribe, } from "./types.cjs";
|
|
11
|
-
export { BUILTIN_LOCALES, CLOSED_FEEDBACK_STATUSES, FEEDBACK_STATUSES, FEEDBACK_TYPES, flattenAnnotation, isClosedStatus, isStoreDuplicate, isStoreNotFound, isStorePersistence, StoreDuplicateError, StoreNotFoundError, StorePersistenceError, } from "./types.cjs";
|
|
15
|
+
export type { AnchorData, AnnotationCreateInput, AnnotationPayload, AnnotationRecord, AnnotationResponse, BuiltinLocale, ClosedFeedbackStatus, ConsoleDiagnosticEntry, ConsoleDiagnosticLevel, DiagnosticsCaptureOptions, DiagnosticsSnapshot, FeedbackCreateInput, FeedbackPage, FeedbackPayload, FeedbackQuery, FeedbackRecord, FeedbackResponse, FeedbackResponseList, FeedbackStatus, FeedbackType, FeedbackUpdateInput, NetworkDiagnosticEntry, OpenFeedbackStatus, PageScope, RectData, ScreenshotRegion, SitepingBaseConfig, SitepingConfig, SitepingDeepLinkOptions, SitepingHeadersOption, SitepingHttpConfig, SitepingIdentity, SitepingInstance, SitepingLocale, SitepingPosition, SitepingPublicEventListener, SitepingPublicEvents, SitepingSkipReason, SitepingStore, SitepingStoreConfig, SitepingTheme, SitepingUnsubscribe, } from "./types.cjs";
|
|
16
|
+
export { BUILTIN_LOCALES, CLOSED_FEEDBACK_STATUSES, CONSOLE_DIAGNOSTIC_LEVELS, FEEDBACK_STATUSES, FEEDBACK_TYPES, flattenAnnotation, isClosedStatus, isStoreDuplicate, isStoreNotFound, isStorePersistence, OPEN_FEEDBACK_STATUSES, StoreDuplicateError, StoreNotFoundError, StorePersistenceError, toFeedbackUpdate, } from "./types.cjs";
|
|
17
|
+
export { errorFromResponse, feedbackQueryToSearchParams, networkErrorFromException } from "./wire.cjs";
|
package/dist/siteping-core.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
export { EMAIL_PATTERN, isValidEmail } from "./email.js";
|
|
1
2
|
export type { SitepingErrorCode } from "./errors.js";
|
|
2
3
|
export { SitepingAuthError, SitepingError, SitepingNetworkError, SitepingValidationError } from "./errors.js";
|
|
3
|
-
export type { FilterResult } from "./filters.js";
|
|
4
|
-
export { applyFeedbackFilters } from "./filters.js";
|
|
4
|
+
export type { FilterResult, Pagination } from "./filters.js";
|
|
5
|
+
export { applyFeedbackFilters, clampPagination, DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT } from "./filters.js";
|
|
6
|
+
export type { I18n, LocaleLoaders, TranslateFunction } from "./i18n.js";
|
|
7
|
+
export { createI18n, interpolate, tWithParams } from "./i18n.js";
|
|
5
8
|
export type { FieldDef, IndexDef, ModelDef, PrismaNativeType, PrismaScalarType, RelationDef, RelationKind, RelationOnDelete, SitepingModelFieldName, SitepingModelName, } from "./schema.js";
|
|
6
9
|
export { isRelationField, isScalarField, SITEPING_MODELS } from "./schema.js";
|
|
7
10
|
export type { ScreenshotStorage } from "./screenshot-storage.js";
|
|
8
|
-
export type {
|
|
11
|
+
export type { CollectionStore, CollectionStoreBackend } from "./store-helpers.js";
|
|
12
|
+
export { buildAnnotationRecord, buildFeedbackRecord, createCollectionStore } from "./store-helpers.js";
|
|
13
|
+
export type { AssertEqual, IfEquals, Prettify, Serialized } from "./type-utils.js";
|
|
9
14
|
export { hasOwn, isRecord } from "./type-utils.js";
|
|
10
|
-
export type { AnchorData, AnnotationCreateInput, AnnotationPayload, AnnotationRecord, AnnotationResponse, BuiltinLocale, ConsoleDiagnosticEntry, ConsoleDiagnosticLevel, DiagnosticsCaptureOptions, DiagnosticsSnapshot, FeedbackCreateInput, FeedbackPage, FeedbackPayload, FeedbackQuery, FeedbackRecord, FeedbackResponse, FeedbackResponseList, FeedbackStatus, FeedbackType, FeedbackUpdateInput, NetworkDiagnosticEntry, PageScope, RectData, ScreenshotRegion, SitepingConfig, SitepingDeepLinkOptions, SitepingHeadersOption, SitepingIdentity, SitepingInstance, SitepingLocale, SitepingPosition, SitepingPublicEventListener, SitepingPublicEvents, SitepingSkipReason, SitepingStore, SitepingTheme, SitepingUnsubscribe, } from "./types.js";
|
|
11
|
-
export { BUILTIN_LOCALES, CLOSED_FEEDBACK_STATUSES, FEEDBACK_STATUSES, FEEDBACK_TYPES, flattenAnnotation, isClosedStatus, isStoreDuplicate, isStoreNotFound, isStorePersistence, StoreDuplicateError, StoreNotFoundError, StorePersistenceError, } from "./types.js";
|
|
15
|
+
export type { AnchorData, AnnotationCreateInput, AnnotationPayload, AnnotationRecord, AnnotationResponse, BuiltinLocale, ClosedFeedbackStatus, ConsoleDiagnosticEntry, ConsoleDiagnosticLevel, DiagnosticsCaptureOptions, DiagnosticsSnapshot, FeedbackCreateInput, FeedbackPage, FeedbackPayload, FeedbackQuery, FeedbackRecord, FeedbackResponse, FeedbackResponseList, FeedbackStatus, FeedbackType, FeedbackUpdateInput, NetworkDiagnosticEntry, OpenFeedbackStatus, PageScope, RectData, ScreenshotRegion, SitepingBaseConfig, SitepingConfig, SitepingDeepLinkOptions, SitepingHeadersOption, SitepingHttpConfig, SitepingIdentity, SitepingInstance, SitepingLocale, SitepingPosition, SitepingPublicEventListener, SitepingPublicEvents, SitepingSkipReason, SitepingStore, SitepingStoreConfig, SitepingTheme, SitepingUnsubscribe, } from "./types.js";
|
|
16
|
+
export { BUILTIN_LOCALES, CLOSED_FEEDBACK_STATUSES, CONSOLE_DIAGNOSTIC_LEVELS, FEEDBACK_STATUSES, FEEDBACK_TYPES, flattenAnnotation, isClosedStatus, isStoreDuplicate, isStoreNotFound, isStorePersistence, OPEN_FEEDBACK_STATUSES, StoreDuplicateError, StoreNotFoundError, StorePersistenceError, toFeedbackUpdate, } from "./types.js";
|
|
17
|
+
export { errorFromResponse, feedbackQueryToSearchParams, networkErrorFromException } from "./wire.js";
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record-construction helpers and the collection-store engine.
|
|
3
|
+
*
|
|
4
|
+
* Every snapshot-style adapter (memory, localStorage, flat file, KV, …)
|
|
5
|
+
* needs the same three ingredients: turn a `FeedbackCreateInput` into a
|
|
6
|
+
* `FeedbackRecord` (null-normalizing optional fields, stamping ids and
|
|
7
|
+
* timestamps), filter/paginate with `applyFeedbackFilters`, and implement
|
|
8
|
+
* the dedup/update/delete choreography of the `SitepingStore` contract.
|
|
9
|
+
*
|
|
10
|
+
* `buildFeedbackRecord` / `buildAnnotationRecord` cover the first part for
|
|
11
|
+
* any adapter. `createCollectionStore` covers all of it: give it `load`,
|
|
12
|
+
* `persist`, and `generateId`, and it returns a fully conformant
|
|
13
|
+
* `SitepingStore` — writing a new snapshot adapter is ~20 lines plus its
|
|
14
|
+
* storage specifics.
|
|
15
|
+
*/
|
|
16
|
+
import type { AnnotationCreateInput, AnnotationRecord, FeedbackCreateInput, FeedbackRecord, SitepingStore } from "./types.cjs";
|
|
17
|
+
/**
|
|
18
|
+
* Build a persisted `AnnotationRecord` from its create input — normalizes
|
|
19
|
+
* the optional anchor fields to `null` and stamps identity/timestamp.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildAnnotationRecord(input: AnnotationCreateInput, ctx: {
|
|
22
|
+
id: string;
|
|
23
|
+
feedbackId: string;
|
|
24
|
+
now: Date;
|
|
25
|
+
}): AnnotationRecord;
|
|
26
|
+
/**
|
|
27
|
+
* Build a persisted `FeedbackRecord` (with its annotations) from a create
|
|
28
|
+
* input — normalizes every optional field to `null` and stamps ids and
|
|
29
|
+
* timestamps. Adapters without external screenshot storage keep the data
|
|
30
|
+
* URL inline on `screenshotUrl`, which is what this helper does; adapters
|
|
31
|
+
* with a `ScreenshotStorage` upload first and override `screenshotUrl`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildFeedbackRecord(input: FeedbackCreateInput, ctx: {
|
|
34
|
+
id: string;
|
|
35
|
+
annotationId: () => string;
|
|
36
|
+
now?: Date;
|
|
37
|
+
}): FeedbackRecord;
|
|
38
|
+
/**
|
|
39
|
+
* Storage primitives behind a collection store. `load`/`persist` may be
|
|
40
|
+
* sync or async — the engine awaits both, so in-memory arrays, localStorage
|
|
41
|
+
* and async KV stores all fit the same three functions.
|
|
42
|
+
*/
|
|
43
|
+
export interface CollectionStoreBackend {
|
|
44
|
+
/**
|
|
45
|
+
* Return the current full snapshot of feedback records. The engine never
|
|
46
|
+
* mutates this array — handing out a live cache is safe.
|
|
47
|
+
*/
|
|
48
|
+
load(): FeedbackRecord[] | Promise<FeedbackRecord[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Persist the full snapshot — always a new array, never the one `load()`
|
|
51
|
+
* returned. Throw `StorePersistenceError` when the write is lost (quota,
|
|
52
|
+
* storage disabled, …) — never swallow the failure. Because the loaded
|
|
53
|
+
* snapshot is left untouched, a throw here leaves a cached `load()` result
|
|
54
|
+
* consistent with durable storage: no phantom record, no half-applied
|
|
55
|
+
* update.
|
|
56
|
+
*/
|
|
57
|
+
persist(feedbacks: FeedbackRecord[]): void | Promise<void>;
|
|
58
|
+
/** Generate a unique id for a new feedback or annotation record. */
|
|
59
|
+
generateId(): string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A `SitepingStore` with the optional `verifyProjectOwnership` guaranteed —
|
|
63
|
+
* what `createCollectionStore` returns.
|
|
64
|
+
*/
|
|
65
|
+
export type CollectionStore = SitepingStore & Required<Pick<SitepingStore, "verifyProjectOwnership">>;
|
|
66
|
+
/**
|
|
67
|
+
* Build a fully conformant `SitepingStore` on top of a snapshot backend.
|
|
68
|
+
*
|
|
69
|
+
* The engine implements the whole store contract: clientId dedup (idempotent
|
|
70
|
+
* create), newest-first ordering, the standard filter/pagination pipeline,
|
|
71
|
+
* `StoreNotFoundError` on missing update/delete, project-scoped bulk delete,
|
|
72
|
+
* and `verifyProjectOwnership`. The snapshot returned by `load` is never
|
|
73
|
+
* mutated: every write hands `persist` a new array, so a failed write leaves
|
|
74
|
+
* a cached snapshot exactly as it was. When `persist` fails during `createFeedback`
|
|
75
|
+
* and the record carries an inline screenshot, the engine retries once
|
|
76
|
+
* without the screenshot (by far the heaviest field) so the text feedback
|
|
77
|
+
* survives a storage-quota hit; if that also fails, the error propagates —
|
|
78
|
+
* returning the record would claim a success that was never persisted.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* export class MemoryStore implements SitepingStore {
|
|
83
|
+
* private feedbacks: FeedbackRecord[] = [];
|
|
84
|
+
* private readonly store = createCollectionStore({
|
|
85
|
+
* load: () => this.feedbacks,
|
|
86
|
+
* persist: (next) => {
|
|
87
|
+
* this.feedbacks = next;
|
|
88
|
+
* },
|
|
89
|
+
* generateId: () => crypto.randomUUID(),
|
|
90
|
+
* });
|
|
91
|
+
* createFeedback = this.store.createFeedback;
|
|
92
|
+
* // …delegate the remaining methods the same way
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function createCollectionStore(backend: CollectionStoreBackend): CollectionStore;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record-construction helpers and the collection-store engine.
|
|
3
|
+
*
|
|
4
|
+
* Every snapshot-style adapter (memory, localStorage, flat file, KV, …)
|
|
5
|
+
* needs the same three ingredients: turn a `FeedbackCreateInput` into a
|
|
6
|
+
* `FeedbackRecord` (null-normalizing optional fields, stamping ids and
|
|
7
|
+
* timestamps), filter/paginate with `applyFeedbackFilters`, and implement
|
|
8
|
+
* the dedup/update/delete choreography of the `SitepingStore` contract.
|
|
9
|
+
*
|
|
10
|
+
* `buildFeedbackRecord` / `buildAnnotationRecord` cover the first part for
|
|
11
|
+
* any adapter. `createCollectionStore` covers all of it: give it `load`,
|
|
12
|
+
* `persist`, and `generateId`, and it returns a fully conformant
|
|
13
|
+
* `SitepingStore` — writing a new snapshot adapter is ~20 lines plus its
|
|
14
|
+
* storage specifics.
|
|
15
|
+
*/
|
|
16
|
+
import type { AnnotationCreateInput, AnnotationRecord, FeedbackCreateInput, FeedbackRecord, SitepingStore } from "./types.js";
|
|
17
|
+
/**
|
|
18
|
+
* Build a persisted `AnnotationRecord` from its create input — normalizes
|
|
19
|
+
* the optional anchor fields to `null` and stamps identity/timestamp.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildAnnotationRecord(input: AnnotationCreateInput, ctx: {
|
|
22
|
+
id: string;
|
|
23
|
+
feedbackId: string;
|
|
24
|
+
now: Date;
|
|
25
|
+
}): AnnotationRecord;
|
|
26
|
+
/**
|
|
27
|
+
* Build a persisted `FeedbackRecord` (with its annotations) from a create
|
|
28
|
+
* input — normalizes every optional field to `null` and stamps ids and
|
|
29
|
+
* timestamps. Adapters without external screenshot storage keep the data
|
|
30
|
+
* URL inline on `screenshotUrl`, which is what this helper does; adapters
|
|
31
|
+
* with a `ScreenshotStorage` upload first and override `screenshotUrl`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildFeedbackRecord(input: FeedbackCreateInput, ctx: {
|
|
34
|
+
id: string;
|
|
35
|
+
annotationId: () => string;
|
|
36
|
+
now?: Date;
|
|
37
|
+
}): FeedbackRecord;
|
|
38
|
+
/**
|
|
39
|
+
* Storage primitives behind a collection store. `load`/`persist` may be
|
|
40
|
+
* sync or async — the engine awaits both, so in-memory arrays, localStorage
|
|
41
|
+
* and async KV stores all fit the same three functions.
|
|
42
|
+
*/
|
|
43
|
+
export interface CollectionStoreBackend {
|
|
44
|
+
/**
|
|
45
|
+
* Return the current full snapshot of feedback records. The engine never
|
|
46
|
+
* mutates this array — handing out a live cache is safe.
|
|
47
|
+
*/
|
|
48
|
+
load(): FeedbackRecord[] | Promise<FeedbackRecord[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Persist the full snapshot — always a new array, never the one `load()`
|
|
51
|
+
* returned. Throw `StorePersistenceError` when the write is lost (quota,
|
|
52
|
+
* storage disabled, …) — never swallow the failure. Because the loaded
|
|
53
|
+
* snapshot is left untouched, a throw here leaves a cached `load()` result
|
|
54
|
+
* consistent with durable storage: no phantom record, no half-applied
|
|
55
|
+
* update.
|
|
56
|
+
*/
|
|
57
|
+
persist(feedbacks: FeedbackRecord[]): void | Promise<void>;
|
|
58
|
+
/** Generate a unique id for a new feedback or annotation record. */
|
|
59
|
+
generateId(): string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A `SitepingStore` with the optional `verifyProjectOwnership` guaranteed —
|
|
63
|
+
* what `createCollectionStore` returns.
|
|
64
|
+
*/
|
|
65
|
+
export type CollectionStore = SitepingStore & Required<Pick<SitepingStore, "verifyProjectOwnership">>;
|
|
66
|
+
/**
|
|
67
|
+
* Build a fully conformant `SitepingStore` on top of a snapshot backend.
|
|
68
|
+
*
|
|
69
|
+
* The engine implements the whole store contract: clientId dedup (idempotent
|
|
70
|
+
* create), newest-first ordering, the standard filter/pagination pipeline,
|
|
71
|
+
* `StoreNotFoundError` on missing update/delete, project-scoped bulk delete,
|
|
72
|
+
* and `verifyProjectOwnership`. The snapshot returned by `load` is never
|
|
73
|
+
* mutated: every write hands `persist` a new array, so a failed write leaves
|
|
74
|
+
* a cached snapshot exactly as it was. When `persist` fails during `createFeedback`
|
|
75
|
+
* and the record carries an inline screenshot, the engine retries once
|
|
76
|
+
* without the screenshot (by far the heaviest field) so the text feedback
|
|
77
|
+
* survives a storage-quota hit; if that also fails, the error propagates —
|
|
78
|
+
* returning the record would claim a success that was never persisted.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* export class MemoryStore implements SitepingStore {
|
|
83
|
+
* private feedbacks: FeedbackRecord[] = [];
|
|
84
|
+
* private readonly store = createCollectionStore({
|
|
85
|
+
* load: () => this.feedbacks,
|
|
86
|
+
* persist: (next) => {
|
|
87
|
+
* this.feedbacks = next;
|
|
88
|
+
* },
|
|
89
|
+
* generateId: () => crypto.randomUUID(),
|
|
90
|
+
* });
|
|
91
|
+
* createFeedback = this.store.createFeedback;
|
|
92
|
+
* // …delegate the remaining methods the same way
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function createCollectionStore(backend: CollectionStoreBackend): CollectionStore;
|
package/dist/type-utils.d.cts
CHANGED
|
@@ -17,61 +17,30 @@
|
|
|
17
17
|
export type Prettify<T> = {
|
|
18
18
|
[K in keyof T]: T[K];
|
|
19
19
|
} & {};
|
|
20
|
-
/**
|
|
21
|
-
* Branded primitive — opaque alias safer than a raw `string` for IDs and
|
|
22
|
-
* other opaque tokens. Cast through `as` at the construction boundary.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* type FeedbackId = Brand<string, "FeedbackId">;
|
|
26
|
-
* const id = "abc" as FeedbackId;
|
|
27
|
-
*/
|
|
28
|
-
export type Brand<T, B extends string> = T & {
|
|
29
|
-
readonly __brand: B;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Tuple type for arrays guaranteed to contain at least one element. Useful
|
|
33
|
-
* for invariants enforced at the type system level.
|
|
34
|
-
*/
|
|
35
|
-
export type NonEmptyArray<T> = readonly [T, ...T[]];
|
|
36
20
|
/**
|
|
37
21
|
* Returns `Y` when `A` is exactly assignable to `B` and vice-versa,
|
|
38
22
|
* otherwise `N`. Powers compile-time equality assertions.
|
|
39
23
|
*/
|
|
40
24
|
export type IfEquals<A, B, Y = true, N = false> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? Y : N;
|
|
41
25
|
/**
|
|
42
|
-
* Compile-time exact-type guard —
|
|
43
|
-
* `Expected`
|
|
44
|
-
*
|
|
26
|
+
* Compile-time exact-type guard — resolves to `true` when `Actual` and
|
|
27
|
+
* `Expected` are identical, `never` otherwise. Assign the result to a
|
|
28
|
+
* `const _lock: AssertEqual<A, B> = true;` so any drift becomes a compile
|
|
29
|
+
* error at the declaration site.
|
|
45
30
|
*/
|
|
46
31
|
export type AssertEqual<Actual, Expected> = IfEquals<Actual, Expected, true, never>;
|
|
47
32
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* Mark every property of `T` as required AND non-nullable. Stricter than
|
|
56
|
-
* `Required<T>` because it also strips `null`.
|
|
33
|
+
* JSON-serialized shape of `T` — the wire form produced by `Response.json()`
|
|
34
|
+
* / `JSON.stringify`: `Date` becomes ISO `string` (nullability preserved),
|
|
35
|
+
* arrays are serialized element-wise, everything else is untouched.
|
|
36
|
+
*
|
|
37
|
+
* Used to derive the `*Response` API types from the `*Record` store types so
|
|
38
|
+
* the two can never drift: add a field to `FeedbackRecord` and
|
|
39
|
+
* `FeedbackResponse` follows automatically.
|
|
57
40
|
*/
|
|
58
|
-
export type
|
|
59
|
-
[K in keyof T]
|
|
41
|
+
export type Serialized<T> = {
|
|
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];
|
|
60
43
|
};
|
|
61
|
-
/**
|
|
62
|
-
* Replace properties of `T` whose names are in `K` with the shape `R[K]`.
|
|
63
|
-
* Preserves the rest. Cheaper than chaining `Omit` + `Pick`.
|
|
64
|
-
*/
|
|
65
|
-
export type Replace<T, K extends keyof T, R extends {
|
|
66
|
-
[P in K]: unknown;
|
|
67
|
-
}> = Prettify<Omit<T, K> & R>;
|
|
68
|
-
/**
|
|
69
|
-
* Deep readonly — recurses through arrays and plain objects, leaves
|
|
70
|
-
* primitives, classes, and built-ins (Date, Map, Set, …) untouched.
|
|
71
|
-
*/
|
|
72
|
-
export type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepReadonly<U>> : T extends object ? T extends (...args: never[]) => unknown ? T : T extends Date | RegExp | Map<unknown, unknown> | Set<unknown> | Promise<unknown> ? T : {
|
|
73
|
-
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
74
|
-
} : T;
|
|
75
44
|
/**
|
|
76
45
|
* Type guard that narrows `value` to a non-null `Record<PropertyKey, unknown>`.
|
|
77
46
|
* Useful when validating arbitrary inputs before reading fields.
|
package/dist/type-utils.d.ts
CHANGED
|
@@ -17,61 +17,30 @@
|
|
|
17
17
|
export type Prettify<T> = {
|
|
18
18
|
[K in keyof T]: T[K];
|
|
19
19
|
} & {};
|
|
20
|
-
/**
|
|
21
|
-
* Branded primitive — opaque alias safer than a raw `string` for IDs and
|
|
22
|
-
* other opaque tokens. Cast through `as` at the construction boundary.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* type FeedbackId = Brand<string, "FeedbackId">;
|
|
26
|
-
* const id = "abc" as FeedbackId;
|
|
27
|
-
*/
|
|
28
|
-
export type Brand<T, B extends string> = T & {
|
|
29
|
-
readonly __brand: B;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Tuple type for arrays guaranteed to contain at least one element. Useful
|
|
33
|
-
* for invariants enforced at the type system level.
|
|
34
|
-
*/
|
|
35
|
-
export type NonEmptyArray<T> = readonly [T, ...T[]];
|
|
36
20
|
/**
|
|
37
21
|
* Returns `Y` when `A` is exactly assignable to `B` and vice-versa,
|
|
38
22
|
* otherwise `N`. Powers compile-time equality assertions.
|
|
39
23
|
*/
|
|
40
24
|
export type IfEquals<A, B, Y = true, N = false> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? Y : N;
|
|
41
25
|
/**
|
|
42
|
-
* Compile-time exact-type guard —
|
|
43
|
-
* `Expected`
|
|
44
|
-
*
|
|
26
|
+
* Compile-time exact-type guard — resolves to `true` when `Actual` and
|
|
27
|
+
* `Expected` are identical, `never` otherwise. Assign the result to a
|
|
28
|
+
* `const _lock: AssertEqual<A, B> = true;` so any drift becomes a compile
|
|
29
|
+
* error at the declaration site.
|
|
45
30
|
*/
|
|
46
31
|
export type AssertEqual<Actual, Expected> = IfEquals<Actual, Expected, true, never>;
|
|
47
32
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* Mark every property of `T` as required AND non-nullable. Stricter than
|
|
56
|
-
* `Required<T>` because it also strips `null`.
|
|
33
|
+
* JSON-serialized shape of `T` — the wire form produced by `Response.json()`
|
|
34
|
+
* / `JSON.stringify`: `Date` becomes ISO `string` (nullability preserved),
|
|
35
|
+
* arrays are serialized element-wise, everything else is untouched.
|
|
36
|
+
*
|
|
37
|
+
* Used to derive the `*Response` API types from the `*Record` store types so
|
|
38
|
+
* the two can never drift: add a field to `FeedbackRecord` and
|
|
39
|
+
* `FeedbackResponse` follows automatically.
|
|
57
40
|
*/
|
|
58
|
-
export type
|
|
59
|
-
[K in keyof T]
|
|
41
|
+
export type Serialized<T> = {
|
|
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];
|
|
60
43
|
};
|
|
61
|
-
/**
|
|
62
|
-
* Replace properties of `T` whose names are in `K` with the shape `R[K]`.
|
|
63
|
-
* Preserves the rest. Cheaper than chaining `Omit` + `Pick`.
|
|
64
|
-
*/
|
|
65
|
-
export type Replace<T, K extends keyof T, R extends {
|
|
66
|
-
[P in K]: unknown;
|
|
67
|
-
}> = Prettify<Omit<T, K> & R>;
|
|
68
|
-
/**
|
|
69
|
-
* Deep readonly — recurses through arrays and plain objects, leaves
|
|
70
|
-
* primitives, classes, and built-ins (Date, Map, Set, …) untouched.
|
|
71
|
-
*/
|
|
72
|
-
export type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepReadonly<U>> : T extends object ? T extends (...args: never[]) => unknown ? T : T extends Date | RegExp | Map<unknown, unknown> | Set<unknown> | Promise<unknown> ? T : {
|
|
73
|
-
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
74
|
-
} : T;
|
|
75
44
|
/**
|
|
76
45
|
* Type guard that narrows `value` to a non-null `Record<PropertyKey, unknown>`.
|
|
77
46
|
* Useful when validating arbitrary inputs before reading fields.
|