@indietabletop/appkit 7.0.0-0 → 7.0.0-rc.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.
- package/lib/AppConfig/AppConfig.tsx +80 -0
- package/lib/AppConfig/formatters.tsx +43 -0
- package/lib/AuthCard/AuthCard.stories.ts +34 -0
- package/lib/AuthCard/AuthCard.tsx +64 -0
- package/lib/AuthCard/style.css.ts +49 -0
- package/lib/CacheProvider.tsx +20 -0
- package/lib/DialogTrigger/index.tsx +36 -0
- package/lib/DocumentTitle/DocumentTitle.tsx +10 -0
- package/lib/EnumMapper.ts +50 -0
- package/lib/ExternalLink.tsx +10 -0
- package/lib/FullscreenDismissBlocker.tsx +23 -0
- package/{dist/HistoryState.d.ts → lib/HistoryState.ts} +5 -2
- package/lib/IndieTabletopClubLogo.tsx +44 -0
- package/lib/IndieTabletopClubSymbol.tsx +37 -0
- package/lib/InfoPage/index.tsx +46 -0
- package/lib/InfoPage/pages.tsx +36 -0
- package/lib/InfoPage/style.css.ts +36 -0
- package/lib/Letterhead/index.tsx +85 -0
- package/lib/Letterhead/stories.tsx +41 -0
- package/lib/Letterhead/style.css.ts +152 -0
- package/lib/LetterheadForm/LetterheadReadonlyTextField.stories.tsx +17 -0
- package/lib/LetterheadForm/LetterheadSubmitError.stories.tsx +19 -0
- package/lib/LetterheadForm/LetterheadTextField.stories.tsx +19 -0
- package/lib/LetterheadForm/index.tsx +137 -0
- package/lib/LetterheadForm/style.css.ts +89 -0
- package/lib/LoadingIndicator.tsx +40 -0
- package/lib/MiddotSeparated/MiddotSeparated.stories.ts +26 -0
- package/lib/MiddotSeparated/MiddotSeparated.tsx +26 -0
- package/lib/MiddotSeparated/style.css.ts +10 -0
- package/lib/ModalDialog/index.tsx +28 -0
- package/lib/ModalDialog/style.css.ts +88 -0
- package/lib/ModernIDB/Cursor.ts +91 -0
- package/lib/ModernIDB/ModernIDB.ts +337 -0
- package/lib/ModernIDB/ModernIDBError.ts +9 -0
- package/lib/ModernIDB/ObjectStore.ts +195 -0
- package/lib/ModernIDB/ObjectStoreIndex.ts +102 -0
- package/lib/ModernIDB/README.md +9 -0
- package/lib/ModernIDB/Transaction.ts +40 -0
- package/lib/ModernIDB/VersionChangeManager.ts +57 -0
- package/lib/ModernIDB/bindings/factory.tsx +165 -0
- package/lib/ModernIDB/bindings/index.ts +2 -0
- package/{dist/ModernIDB/bindings/types.d.ts → lib/ModernIDB/bindings/types.ts} +32 -13
- package/lib/ModernIDB/bindings/utils.tsx +32 -0
- package/lib/ModernIDB/index.ts +10 -0
- package/lib/ModernIDB/types.ts +120 -0
- package/lib/ModernIDB/utils.ts +51 -0
- package/lib/QRCode/QRCode.stories.tsx +41 -0
- package/lib/QRCode/QRCode.tsx +54 -0
- package/lib/QRCode/style.css.ts +23 -0
- package/lib/ReleaseInfo/index.tsx +29 -0
- package/lib/RulesetResolver.ts +214 -0
- package/lib/SafariCheck/SafariCheck.stories.tsx +99 -0
- package/lib/SafariCheck/SafariCheck.tsx +273 -0
- package/lib/SafariCheck/addToDock.svg +13 -0
- package/lib/SafariCheck/addToHomeScreen.svg +12 -0
- package/lib/SafariCheck/safari.svg +32 -0
- package/lib/SafariCheck/shareIcon.svg +11 -0
- package/lib/SafariCheck/style.css.ts +106 -0
- package/lib/ServiceWorkerHandler.tsx +53 -0
- package/lib/ShareButton/ShareButton.stories.tsx +58 -0
- package/lib/ShareButton/ShareButton.tsx +153 -0
- package/lib/ShareButton/test.css.ts +3 -0
- package/lib/SubscribeCard/LetterheadInfoCard.tsx +23 -0
- package/lib/SubscribeCard/SubscribeByEmailCard.stories.tsx +69 -0
- package/lib/SubscribeCard/SubscribeByEmailCard.tsx +183 -0
- package/lib/SubscribeCard/SubscribeByPledgeCard.stories.tsx +133 -0
- package/lib/SubscribeCard/SubscribeByPledgeCard.tsx +127 -0
- package/lib/SubscribeCard/style.css.ts +14 -0
- package/lib/Sync/SyncIcon.stories.tsx +67 -0
- package/lib/Sync/SyncIcon.tsx +102 -0
- package/lib/Sync/SyncLog.tsx +222 -0
- package/lib/Sync/SyncLogList.stories.tsx +219 -0
- package/lib/Sync/style.css.ts +126 -0
- package/lib/account/AccountIcon.tsx +15 -0
- package/lib/account/AccountIssueView.tsx +44 -0
- package/lib/account/AlreadyLoggedInView.tsx +47 -0
- package/lib/account/CurrentUserFetcher.stories.tsx +292 -0
- package/lib/account/CurrentUserFetcher.tsx +118 -0
- package/lib/account/FailureFallbackView.tsx +36 -0
- package/lib/account/JoinCard.stories.tsx +257 -0
- package/lib/account/JoinCard.tsx +301 -0
- package/lib/account/LoadingView.tsx +14 -0
- package/lib/account/LoginCard.stories.tsx +288 -0
- package/lib/account/LoginCard.tsx +100 -0
- package/lib/account/LoginView.tsx +151 -0
- package/lib/account/NoConnectionView.tsx +34 -0
- package/lib/account/PasswordResetCard.stories.tsx +242 -0
- package/lib/account/PasswordResetCard.tsx +296 -0
- package/lib/account/UserMismatchView.tsx +62 -0
- package/lib/account/VerifyPage.tsx +195 -0
- package/lib/account/iconMask.svg +3 -0
- package/lib/account/style.css.ts +81 -0
- package/{dist/account/types.d.ts → lib/account/types.ts} +6 -3
- package/lib/account/useFetchCurrentUser.tsx +63 -0
- package/lib/account/useRedirectPath.ts +21 -0
- package/lib/animations.css.ts +17 -0
- package/lib/append-copy-to-text.ts +35 -0
- package/lib/async-op.ts +286 -0
- package/lib/atomic.css.ts +11 -0
- package/{dist/caught-value.d.ts → lib/caught-value.ts} +11 -1
- package/{dist/class-names.d.ts → lib/class-names.ts} +17 -6
- package/lib/client.ts +662 -0
- package/lib/common.css.ts +48 -0
- package/lib/copyrightRange.ts +10 -0
- package/lib/createSafeStorage.ts +91 -0
- package/lib/createStrictContext.ts +15 -0
- package/lib/failureMessages.ts +108 -0
- package/lib/form/FormSubmitButton.tsx +58 -0
- package/lib/form/SubmitErrorAlert.tsx +21 -0
- package/lib/form/style.css.ts +9 -0
- package/lib/globals.css.ts +62 -0
- package/lib/groupBy.ts +25 -0
- package/lib/hrefs.ts +48 -0
- package/lib/idToDate.ts +8 -0
- package/lib/ids.ts +6 -0
- package/lib/index.ts +75 -0
- package/lib/internal.css.ts +10 -0
- package/lib/mailto.ts +40 -0
- package/lib/media.ts +50 -0
- package/lib/random.ts +19 -0
- package/lib/result/swr.ts +18 -0
- package/{dist/sleep.d.ts → lib/sleep.ts} +3 -1
- package/lib/store/index.tsx +294 -0
- package/lib/store/store.ts +482 -0
- package/lib/store/types.ts +45 -0
- package/lib/store/utils.ts +54 -0
- package/lib/storybook/decorators.tsx +10 -0
- package/lib/structs.ts +3 -0
- package/{dist/typeguards.d.ts → lib/typeguards.ts} +3 -1
- package/{dist/types.d.ts → lib/types.ts} +23 -12
- package/lib/unique.ts +24 -0
- package/lib/use-async-op.ts +16 -0
- package/lib/use-document-background-color.ts +16 -0
- package/lib/use-form.ts +78 -0
- package/lib/use-is-installed.ts +17 -0
- package/lib/use-media-query.ts +21 -0
- package/lib/use-reverting-state.ts +32 -0
- package/lib/use-scroll-restoration.ts +99 -0
- package/lib/useEnsureValue.ts +31 -0
- package/lib/useInvokeClient.ts +54 -0
- package/lib/useIsVisible.ts +27 -0
- package/lib/utm.ts +92 -0
- package/lib/validations.ts +25 -0
- package/lib/vars.css.ts +13 -0
- package/package.json +23 -29
- package/dist/AppConfig/AppConfig.d.ts +0 -29
- package/dist/AuthCard/AuthCard.d.ts +0 -10
- package/dist/AuthCard/AuthCard.stories.d.ts +0 -34
- package/dist/AuthCard/style.css.d.ts +0 -23
- package/dist/DialogTrigger/index.d.ts +0 -13
- package/dist/DocumentTitle/DocumentTitle.d.ts +0 -3
- package/dist/EnumMapper.d.ts +0 -25
- package/dist/ExternalLink.d.ts +0 -3
- package/dist/FullscreenDismissBlocker.d.ts +0 -5
- package/dist/IndieTabletopClubLogo.d.ts +0 -7
- package/dist/IndieTabletopClubSymbol.d.ts +0 -7
- package/dist/InfoPage/index.d.ts +0 -8
- package/dist/InfoPage/pages.d.ts +0 -2
- package/dist/InfoPage/style.css.d.ts +0 -5
- package/dist/Letterhead/index.d.ts +0 -19
- package/dist/Letterhead/stories.d.ts +0 -13
- package/dist/Letterhead/style.css.d.ts +0 -46
- package/dist/LetterheadForm/LetterheadReadonlyTextField.stories.d.ts +0 -17
- package/dist/LetterheadForm/LetterheadSubmitError.stories.d.ts +0 -11
- package/dist/LetterheadForm/LetterheadTextField.stories.d.ts +0 -336
- package/dist/LetterheadForm/index.d.ts +0 -44
- package/dist/LetterheadForm/style.css.d.ts +0 -8
- package/dist/LoadingIndicator.d.ts +0 -3
- package/dist/MiddotSeparated/MiddotSeparated.d.ts +0 -8
- package/dist/MiddotSeparated/MiddotSeparated.stories.d.ts +0 -586
- package/dist/MiddotSeparated/style.css.d.ts +0 -1
- package/dist/ModalDialog/index.d.ts +0 -12
- package/dist/ModalDialog/style.css.d.ts +0 -58
- package/dist/ModernIDB/Cursor.d.ts +0 -56
- package/dist/ModernIDB/ModernIDB.d.ts +0 -66
- package/dist/ModernIDB/ModernIDBError.d.ts +0 -3
- package/dist/ModernIDB/ObjectStore.d.ts +0 -112
- package/dist/ModernIDB/ObjectStoreIndex.d.ts +0 -53
- package/dist/ModernIDB/Transaction.d.ts +0 -16
- package/dist/ModernIDB/VersionChangeManager.d.ts +0 -30
- package/dist/ModernIDB/bindings/factory.d.ts +0 -12
- package/dist/ModernIDB/bindings/index.d.ts +0 -2
- package/dist/ModernIDB/bindings/utils.d.ts +0 -2
- package/dist/ModernIDB/index.d.ts +0 -10
- package/dist/ModernIDB/types.d.ts +0 -88
- package/dist/ModernIDB/utils.d.ts +0 -4
- package/dist/QRCode/QRCode.d.ts +0 -7
- package/dist/QRCode/QRCode.stories.d.ts +0 -33
- package/dist/QRCode/style.css.d.ts +0 -4
- package/dist/ReleaseInfo/index.d.ts +0 -5
- package/dist/RulesetResolver.d.ts +0 -87
- package/dist/SafariCheck/SafariCheck.d.ts +0 -23
- package/dist/SafariCheck/SafariCheck.stories.d.ts +0 -73
- package/dist/SafariCheck/style.css.d.ts +0 -17
- package/dist/ServiceWorkerHandler.d.ts +0 -11
- package/dist/ShareButton/ShareButton.d.ts +0 -57
- package/dist/ShareButton/ShareButton.stories.d.ts +0 -1577
- package/dist/ShareButton/test.css.d.ts +0 -1
- package/dist/SubscribeCard/LetterheadInfoCard.d.ts +0 -2
- package/dist/SubscribeCard/SubscribeByEmailCard.d.ts +0 -24
- package/dist/SubscribeCard/SubscribeByEmailCard.stories.d.ts +0 -10
- package/dist/SubscribeCard/SubscribeByPledgeCard.d.ts +0 -36
- package/dist/SubscribeCard/SubscribeByPledgeCard.stories.d.ts +0 -65
- package/dist/SubscribeCard/style.css.d.ts +0 -4
- package/dist/account/AccountIssueView.d.ts +0 -3
- package/dist/account/AlreadyLoggedInView.d.ts +0 -5
- package/dist/account/CurrentUserFetcher.d.ts +0 -20
- package/dist/account/CurrentUserFetcher.stories.d.ts +0 -136
- package/dist/account/FailureFallbackView.d.ts +0 -1
- package/dist/account/JoinCard.d.ts +0 -14
- package/dist/account/JoinCard.stories.d.ts +0 -143
- package/dist/account/LoadingView.d.ts +0 -1
- package/dist/account/LoginCard.d.ts +0 -39
- package/dist/account/LoginCard.stories.d.ts +0 -217
- package/dist/account/LoginView.d.ts +0 -10
- package/dist/account/NoConnectionView.d.ts +0 -4
- package/dist/account/PasswordResetCard.d.ts +0 -15
- package/dist/account/PasswordResetCard.stories.d.ts +0 -128
- package/dist/account/UserMismatchView.d.ts +0 -6
- package/dist/account/VerifyPage.d.ts +0 -13
- package/dist/account/style.css.d.ts +0 -10
- package/dist/account/useFetchCurrentUser.d.ts +0 -28
- package/dist/account/useRedirectPath.d.ts +0 -6
- package/dist/animations.css.d.ts +0 -3
- package/dist/append-copy-to-text.d.ts +0 -10
- package/dist/append-copy-to-text.test.d.ts +0 -1
- package/dist/appkit.css +0 -1
- package/dist/appkit.js +0 -10692
- package/dist/async-op.d.ts +0 -101
- package/dist/atomic.css.d.ts +0 -6
- package/dist/client.d.ts +0 -424
- package/dist/common.css.d.ts +0 -5
- package/dist/copyrightRange.d.ts +0 -1
- package/dist/copyrightRange.test.d.ts +0 -1
- package/dist/createSafeStorage.d.ts +0 -34
- package/dist/failureMessages.d.ts +0 -20
- package/dist/failureMessages.test.d.ts +0 -1
- package/dist/form/FormSubmitButton.d.ts +0 -17
- package/dist/form/SubmitErrorAlert.d.ts +0 -5
- package/dist/form/style.css.d.ts +0 -3
- package/dist/globals.css.d.ts +0 -0
- package/dist/groupBy.d.ts +0 -1
- package/dist/groupBy.test.d.ts +0 -1
- package/dist/hrefs.d.ts +0 -32
- package/dist/hrefs.test.d.ts +0 -1
- package/dist/idToDate.d.ts +0 -5
- package/dist/idToDate.test.d.ts +0 -1
- package/dist/ids.d.ts +0 -1
- package/dist/ids.test.d.ts +0 -1
- package/dist/index.d.ts +0 -64
- package/dist/internal.css.d.ts +0 -2
- package/dist/mailto.d.ts +0 -8
- package/dist/mailto.test.d.ts +0 -1
- package/dist/media.d.ts +0 -39
- package/dist/random.d.ts +0 -3
- package/dist/result/swr.d.ts +0 -4
- package/dist/store/index.d.ts +0 -237
- package/dist/store/store.d.ts +0 -144
- package/dist/store/types.d.ts +0 -49
- package/dist/store/utils.d.ts +0 -10
- package/dist/storybook/decorators.d.ts +0 -3
- package/dist/structs.d.ts +0 -1
- package/dist/typeguards.test.d.ts +0 -1
- package/dist/unique.d.ts +0 -10
- package/dist/unique.test.d.ts +0 -1
- package/dist/use-async-op.d.ts +0 -6
- package/dist/use-document-background-color.d.ts +0 -4
- package/dist/use-form.d.ts +0 -29
- package/dist/use-is-installed.d.ts +0 -8
- package/dist/use-media-query.d.ts +0 -1
- package/dist/use-reverting-state.d.ts +0 -5
- package/dist/use-scroll-restoration.d.ts +0 -25
- package/dist/useEnsureValue.d.ts +0 -6
- package/dist/useInvokeClient.d.ts +0 -25
- package/dist/useIsVisible.d.ts +0 -4
- package/dist/utm.d.ts +0 -58
- package/dist/utm.test.d.ts +0 -1
- package/dist/validations.d.ts +0 -3
- package/dist/vars.css.d.ts +0 -10
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { style } from "@vanilla-extract/css";
|
|
2
|
+
import { recipe } from "@vanilla-extract/recipes";
|
|
3
|
+
import { MinWidth } from "../media.ts";
|
|
4
|
+
import { ZIndex } from "../vars.css.ts";
|
|
5
|
+
|
|
6
|
+
const scaleTransition = {
|
|
7
|
+
transition: "transform 200ms, opacity 200ms",
|
|
8
|
+
transform: "scale(1.1)",
|
|
9
|
+
|
|
10
|
+
selectors: {
|
|
11
|
+
"&[data-enter]": {
|
|
12
|
+
opacity: 1,
|
|
13
|
+
transform: "scale(1)",
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
"&[data-leave]": {
|
|
17
|
+
opacity: 0,
|
|
18
|
+
transform: "scale(0.9)",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const translateTransition = {
|
|
24
|
+
transition: "transform 200ms, opacity 200ms",
|
|
25
|
+
transform: "translateY(5rem)",
|
|
26
|
+
|
|
27
|
+
selectors: {
|
|
28
|
+
"&[data-enter]": {
|
|
29
|
+
opacity: 1,
|
|
30
|
+
transform: "translateY(0)",
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
"&[data-leave]": {
|
|
34
|
+
opacity: 0,
|
|
35
|
+
transform: "translateY(5rem)",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const dialog = recipe({
|
|
41
|
+
base: {
|
|
42
|
+
position: "fixed",
|
|
43
|
+
inset: 0,
|
|
44
|
+
zIndex: ZIndex.DIALOG,
|
|
45
|
+
margin: "auto",
|
|
46
|
+
overflow: "auto",
|
|
47
|
+
opacity: 0,
|
|
48
|
+
backgroundColor: "white",
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
variants: {
|
|
52
|
+
size: {
|
|
53
|
+
large: {
|
|
54
|
+
...translateTransition,
|
|
55
|
+
inlineSize: "100%",
|
|
56
|
+
blockSize: "100%",
|
|
57
|
+
|
|
58
|
+
"@media": {
|
|
59
|
+
[MinWidth.MEDIUM]: {
|
|
60
|
+
...scaleTransition,
|
|
61
|
+
blockSize: "fit-content",
|
|
62
|
+
maxInlineSize: "40rem",
|
|
63
|
+
maxBlockSize: "90%",
|
|
64
|
+
borderRadius: "1rem",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
small: {
|
|
70
|
+
...scaleTransition,
|
|
71
|
+
inlineSize: "min(24rem, 90svw)",
|
|
72
|
+
blockSize: "fit-content",
|
|
73
|
+
borderRadius: "1rem",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export const backdrop = style({
|
|
80
|
+
backgroundColor: "black",
|
|
81
|
+
opacity: 0,
|
|
82
|
+
transition: "opacity 200ms",
|
|
83
|
+
selectors: {
|
|
84
|
+
"&[data-enter]": {
|
|
85
|
+
opacity: 0.4,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
2
|
+
|
|
3
|
+
import { requestToPromise } from "./utils.ts";
|
|
4
|
+
|
|
5
|
+
export class Cursor<C extends IDBCursor = IDBCursor> {
|
|
6
|
+
idbCursor: C;
|
|
7
|
+
|
|
8
|
+
constructor(idbCursor: C) {
|
|
9
|
+
this.idbCursor = idbCursor;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get key() {
|
|
13
|
+
return this.idbCursor.key;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get primaryKey() {
|
|
17
|
+
return this.idbCursor.primaryKey;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get direction() {
|
|
21
|
+
return this.idbCursor.direction;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Advances the cursor through the next count records in range.
|
|
26
|
+
*
|
|
27
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBCursor/advance
|
|
28
|
+
*/
|
|
29
|
+
advance(count: number): void {
|
|
30
|
+
this.idbCursor.advance(count);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Advances the cursor to the next record in range.
|
|
34
|
+
*
|
|
35
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBCursor/continue)
|
|
36
|
+
*/
|
|
37
|
+
continue(key?: IDBValidKey): void {
|
|
38
|
+
this.idbCursor.continue(key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class CursorWithValue<Item> extends Cursor<IDBCursorWithValue> {
|
|
43
|
+
get value(): Item {
|
|
44
|
+
return this.idbCursor.value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Delete the record pointed at by the cursor.
|
|
49
|
+
*
|
|
50
|
+
* If successful, request's result will be undefined.
|
|
51
|
+
*
|
|
52
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBCursor/delete)
|
|
53
|
+
*/
|
|
54
|
+
delete(): Promise<undefined> {
|
|
55
|
+
return requestToPromise(this.idbCursor.delete());
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Updated the record pointed at by the cursor with a new value.
|
|
59
|
+
*
|
|
60
|
+
* Throws a "DataError" DOMException if the effective object store uses in-line keys and the key would have changed.
|
|
61
|
+
*
|
|
62
|
+
* If successful, request's result will be the record's key.
|
|
63
|
+
*
|
|
64
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBCursor/update)
|
|
65
|
+
*/
|
|
66
|
+
update(value: Item): Promise<IDBValidKey> {
|
|
67
|
+
return requestToPromise(this.idbCursor.update(value));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class IndexCursor extends Cursor {
|
|
72
|
+
/**
|
|
73
|
+
* Advances the cursor to the next record in range matching or after key and primaryKey. Throws an "InvalidAccessError" DOMException if the source is not an index.
|
|
74
|
+
*
|
|
75
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBCursor/continuePrimaryKey)
|
|
76
|
+
*/
|
|
77
|
+
continuePrimaryKey(key: IDBValidKey, primaryKey: IDBValidKey): void {
|
|
78
|
+
this.idbCursor.continuePrimaryKey(key, primaryKey);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export class IndexCursorWithValue<Item> extends CursorWithValue<Item> {
|
|
83
|
+
/**
|
|
84
|
+
* Advances the cursor to the next record in range matching or after key and primaryKey. Throws an "InvalidAccessError" DOMException if the source is not an index.
|
|
85
|
+
*
|
|
86
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBCursor/continuePrimaryKey)
|
|
87
|
+
*/
|
|
88
|
+
continuePrimaryKey(key: IDBValidKey, primaryKey: IDBValidKey): void {
|
|
89
|
+
this.idbCursor.continuePrimaryKey(key, primaryKey);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/prefer-promise-reject-errors */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
3
|
+
|
|
4
|
+
import { ModernIDBError } from "./ModernIDBError.ts";
|
|
5
|
+
import { ObjectStore } from "./ObjectStore.ts";
|
|
6
|
+
import type {
|
|
7
|
+
BlockingHandler,
|
|
8
|
+
ModernIDBIndexes,
|
|
9
|
+
ModernIDBSchema,
|
|
10
|
+
ModernIDBState,
|
|
11
|
+
OpenRequestHandlers,
|
|
12
|
+
TransactionMode,
|
|
13
|
+
VersionChangeHandler,
|
|
14
|
+
} from "./types.ts";
|
|
15
|
+
import { openRequestToPromise, transactionToPromise } from "./utils.ts";
|
|
16
|
+
import { VersionChangeManager } from "./VersionChangeManager.ts";
|
|
17
|
+
|
|
18
|
+
export class TransactionEvent<StoreName extends string> extends CustomEvent<{
|
|
19
|
+
storeNames: StoreName[];
|
|
20
|
+
}> {
|
|
21
|
+
constructor(type: TransactionMode, storeNames: StoreName[]) {
|
|
22
|
+
super(type, { detail: { storeNames } });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type TransactionOptions = IDBTransactionOptions & {
|
|
27
|
+
/**
|
|
28
|
+
* Do not emit events when this transaction completes.
|
|
29
|
+
*/
|
|
30
|
+
noEmit?: boolean;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type DatabaseProps = {
|
|
34
|
+
name: string;
|
|
35
|
+
version: number;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export class ModernIDB<
|
|
39
|
+
Schema extends ModernIDBSchema,
|
|
40
|
+
IndexNames extends ModernIDBIndexes<Schema>,
|
|
41
|
+
> {
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly version: number;
|
|
44
|
+
|
|
45
|
+
protected state: ModernIDBState = "closed";
|
|
46
|
+
protected idbDatabase: IDBDatabase | null = null;
|
|
47
|
+
|
|
48
|
+
private eventTarget: EventTarget;
|
|
49
|
+
private onBlocking?: BlockingHandler<Schema, IndexNames>;
|
|
50
|
+
private onUpgrade?: VersionChangeHandler<Schema, IndexNames>;
|
|
51
|
+
private onInit?: VersionChangeHandler<Schema, IndexNames>;
|
|
52
|
+
|
|
53
|
+
constructor(props: DatabaseProps & OpenRequestHandlers<Schema, IndexNames>) {
|
|
54
|
+
this.eventTarget = new EventTarget();
|
|
55
|
+
this.name = props.name;
|
|
56
|
+
this.version = props.version;
|
|
57
|
+
|
|
58
|
+
this.onInit = props.onInit;
|
|
59
|
+
this.onUpgrade = props.onUpgrade;
|
|
60
|
+
this.onBlocking = props.onBlocking;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public addEventListener(
|
|
64
|
+
type: TransactionMode,
|
|
65
|
+
callback: (event: TransactionEvent<string & keyof Schema>) => void,
|
|
66
|
+
options?: boolean | AddEventListenerOptions,
|
|
67
|
+
): void {
|
|
68
|
+
this.eventTarget.addEventListener(
|
|
69
|
+
type,
|
|
70
|
+
|
|
71
|
+
// The EventTarget should only have events dispatched by ModernIDB,
|
|
72
|
+
// meaning that it should be safe to assume that the event will be
|
|
73
|
+
// a TransactionEvent.
|
|
74
|
+
callback as EventListener,
|
|
75
|
+
options,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public removeEventListener(
|
|
80
|
+
type: TransactionMode,
|
|
81
|
+
callback: (event: TransactionEvent<string & keyof Schema>) => void,
|
|
82
|
+
options?: boolean | EventListenerOptions,
|
|
83
|
+
): void {
|
|
84
|
+
this.eventTarget.removeEventListener(
|
|
85
|
+
type,
|
|
86
|
+
|
|
87
|
+
// The EventTarget should only have events dispatched by ModernIDB,
|
|
88
|
+
// meaning that it should be safe to assume that the event will be
|
|
89
|
+
// a TransactionEvent.
|
|
90
|
+
callback as EventListener,
|
|
91
|
+
options,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Opens a connection to IndexedDB.
|
|
97
|
+
*
|
|
98
|
+
* ModernIDB instance must be in a `closed` state, otherwise an
|
|
99
|
+
* `InvalidConnectionStateError` will be thrown.
|
|
100
|
+
*
|
|
101
|
+
* If the database needs to upgrade (i.e. supplied version is higher than
|
|
102
|
+
* the current version), but there are existing connections that don't
|
|
103
|
+
* close on `versionchange` event (the onBlocking handler), an
|
|
104
|
+
* `OpenRequestBlockedError` will be thrown.
|
|
105
|
+
*
|
|
106
|
+
* Additional browser-specific exceptions can also be thrown. Make
|
|
107
|
+
* sure to inspect any error's `name` property to differentiate
|
|
108
|
+
* between the various types of errors that could occur.
|
|
109
|
+
*/
|
|
110
|
+
async open(handlers?: OpenRequestHandlers<Schema, IndexNames>) {
|
|
111
|
+
if (this.state !== "closed") {
|
|
112
|
+
throw new ModernIDBError(
|
|
113
|
+
"InvalidConnectionStateError",
|
|
114
|
+
`Cannot open connection to database '${this.name}'. Instance must ` +
|
|
115
|
+
`be in a 'closed' state in order to be opened, but current ` +
|
|
116
|
+
`state is '${this.state}'.`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.state = "opening";
|
|
121
|
+
|
|
122
|
+
// Override handlers supplied in the constructor
|
|
123
|
+
Object.assign(this, handlers);
|
|
124
|
+
|
|
125
|
+
const handleInit = this.onInit;
|
|
126
|
+
const handleBlocking = this.onBlocking;
|
|
127
|
+
const handleUpgrade = this.onUpgrade;
|
|
128
|
+
|
|
129
|
+
return new Promise<Event>((resolve, reject) => {
|
|
130
|
+
try {
|
|
131
|
+
const request = indexedDB.open(this.name, this.version);
|
|
132
|
+
|
|
133
|
+
if (handleUpgrade || handleInit) {
|
|
134
|
+
request.addEventListener(
|
|
135
|
+
"upgradeneeded",
|
|
136
|
+
(event) => {
|
|
137
|
+
const idbDatabase = request.result;
|
|
138
|
+
const idbTransaction = request.transaction!;
|
|
139
|
+
|
|
140
|
+
const manager = new VersionChangeManager<Schema, IndexNames>({
|
|
141
|
+
idbDatabase,
|
|
142
|
+
idbTransaction,
|
|
143
|
+
event,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
if (event.oldVersion === 0) {
|
|
148
|
+
handleInit?.({ event, manager, db: this });
|
|
149
|
+
} else {
|
|
150
|
+
handleUpgrade?.({ event, manager, db: this });
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error(error);
|
|
154
|
+
idbTransaction.abort();
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{ once: true },
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
request.addEventListener(
|
|
162
|
+
"blocked",
|
|
163
|
+
() => {
|
|
164
|
+
this.state = "closed";
|
|
165
|
+
reject(
|
|
166
|
+
new ModernIDBError(
|
|
167
|
+
"OpenRequestBlockedError",
|
|
168
|
+
|
|
169
|
+
`ModernIDB connection could not be opened because there ` +
|
|
170
|
+
`is an open connection preventing a 'versionchange' ` +
|
|
171
|
+
`transaction from being created.`,
|
|
172
|
+
),
|
|
173
|
+
);
|
|
174
|
+
},
|
|
175
|
+
{ once: true },
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
request.addEventListener(
|
|
179
|
+
"success",
|
|
180
|
+
(event) => {
|
|
181
|
+
if (this.state === "opening") {
|
|
182
|
+
const idb = request.result;
|
|
183
|
+
this.idbDatabase = idb;
|
|
184
|
+
|
|
185
|
+
if (handleBlocking) {
|
|
186
|
+
this.idbDatabase.addEventListener("versionchange", (event) => {
|
|
187
|
+
handleBlocking({ event, db: this });
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
this.state = "open";
|
|
192
|
+
resolve(event);
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{ once: true },
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
request.addEventListener(
|
|
199
|
+
"error",
|
|
200
|
+
() => {
|
|
201
|
+
this.state = "closed";
|
|
202
|
+
reject(request.error);
|
|
203
|
+
},
|
|
204
|
+
{ once: true },
|
|
205
|
+
);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
reject(error);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
close() {
|
|
213
|
+
this.state = "closed";
|
|
214
|
+
|
|
215
|
+
this.idbDatabase?.close();
|
|
216
|
+
this.idbDatabase = null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
isOpen(): this is this & { idbDatabase: IDBDatabase } {
|
|
220
|
+
return !!this.idbDatabase;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private assertOpen(
|
|
224
|
+
hint: string,
|
|
225
|
+
): asserts this is this & { idbDatabase: IDBDatabase } {
|
|
226
|
+
if (!this.isOpen()) {
|
|
227
|
+
throw new ModernIDBError("InvalidConnectionStateError", hint);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
transaction<StoreName extends string & keyof Schema>(
|
|
232
|
+
name: StoreName,
|
|
233
|
+
mode?: TransactionMode,
|
|
234
|
+
options?: TransactionOptions,
|
|
235
|
+
): [
|
|
236
|
+
ObjectStore<
|
|
237
|
+
Schema[StoreName],
|
|
238
|
+
IndexNames[StoreName] extends string ? IndexNames[StoreName] : never
|
|
239
|
+
>,
|
|
240
|
+
Promise<Event>,
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
transaction<StoreNamesArray extends readonly (string & keyof Schema)[] | []>(
|
|
244
|
+
names: StoreNamesArray,
|
|
245
|
+
mode?: TransactionMode,
|
|
246
|
+
options?: TransactionOptions,
|
|
247
|
+
): [
|
|
248
|
+
{
|
|
249
|
+
-readonly [Index in keyof StoreNamesArray]: ObjectStore<
|
|
250
|
+
Schema[StoreNamesArray[Index]],
|
|
251
|
+
IndexNames[StoreNamesArray[Index]] extends string
|
|
252
|
+
? IndexNames[StoreNamesArray[Index]]
|
|
253
|
+
: never
|
|
254
|
+
>;
|
|
255
|
+
},
|
|
256
|
+
Promise<Event>,
|
|
257
|
+
];
|
|
258
|
+
|
|
259
|
+
transaction(
|
|
260
|
+
nameOrNames: string | string[],
|
|
261
|
+
mode?: TransactionMode,
|
|
262
|
+
options?: TransactionOptions,
|
|
263
|
+
) {
|
|
264
|
+
const transactionMode = mode ?? "readonly";
|
|
265
|
+
|
|
266
|
+
this.assertOpen(
|
|
267
|
+
`The "transaction" method can only be called on an instance that is ` +
|
|
268
|
+
`in the "open" state, but current state is: "${this.state}".`,
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
const transaction = this.idbDatabase.transaction(
|
|
272
|
+
nameOrNames,
|
|
273
|
+
transactionMode,
|
|
274
|
+
options,
|
|
275
|
+
);
|
|
276
|
+
const complete = transactionToPromise(transaction);
|
|
277
|
+
|
|
278
|
+
if (!options?.noEmit) {
|
|
279
|
+
// Generally, it is best practice to always attach then/catch handlers to
|
|
280
|
+
// promises. However, in this case, these should be attached in user-code,
|
|
281
|
+
// as it doesn't make sense to try to handle errors from here.
|
|
282
|
+
//
|
|
283
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
284
|
+
complete.then((event) => {
|
|
285
|
+
this.eventTarget.dispatchEvent(
|
|
286
|
+
new TransactionEvent(
|
|
287
|
+
transactionMode,
|
|
288
|
+
Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames],
|
|
289
|
+
),
|
|
290
|
+
);
|
|
291
|
+
return event;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (Array.isArray(nameOrNames)) {
|
|
296
|
+
const objectStores = nameOrNames.map(
|
|
297
|
+
(name) => new ObjectStore(transaction.objectStore(name)),
|
|
298
|
+
);
|
|
299
|
+
return [objectStores, complete];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return [new ObjectStore(transaction.objectStore(nameOrNames)), complete];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async deleteFromStore(
|
|
306
|
+
storeName: string & keyof Schema,
|
|
307
|
+
query: IDBValidKey | IDBKeyRange,
|
|
308
|
+
options?: IDBTransactionOptions,
|
|
309
|
+
) {
|
|
310
|
+
const [store, done] = this.transaction(storeName, "readwrite", options);
|
|
311
|
+
await Promise.all([store.delete(query), done]);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async getFromStore<StoreName extends string & keyof Schema>(
|
|
315
|
+
storeName: StoreName,
|
|
316
|
+
query: IDBValidKey | IDBKeyRange,
|
|
317
|
+
options?: IDBTransactionOptions,
|
|
318
|
+
) {
|
|
319
|
+
const [store, done] = this.transaction(storeName, "readonly", options);
|
|
320
|
+
const [data] = await Promise.all([store.get(query), done]);
|
|
321
|
+
return data;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async putToStore<StoreName extends string & keyof Schema>(
|
|
325
|
+
storeName: StoreName,
|
|
326
|
+
value: Schema[StoreName],
|
|
327
|
+
key?: IDBValidKey,
|
|
328
|
+
) {
|
|
329
|
+
const [store, done] = this.transaction(storeName, "readwrite");
|
|
330
|
+
const [itemKey] = await Promise.all([store.put(value, key), done]);
|
|
331
|
+
return itemKey;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function deleteDatabase(name: string) {
|
|
336
|
+
return openRequestToPromise(indexedDB.deleteDatabase(name));
|
|
337
|
+
}
|