rwsdk 1.0.0-beta.3 → 1.0.0-beta.30
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/lib/constants.d.mts +1 -0
- package/dist/lib/constants.mjs +7 -4
- package/dist/lib/e2e/browser.mjs +6 -2
- package/dist/lib/e2e/constants.d.mts +16 -0
- package/dist/lib/e2e/constants.mjs +77 -0
- package/dist/lib/e2e/dev.mjs +37 -49
- package/dist/lib/e2e/environment.d.mts +2 -0
- package/dist/lib/e2e/environment.mjs +202 -65
- package/dist/lib/e2e/index.d.mts +1 -0
- package/dist/lib/e2e/index.mjs +1 -0
- package/dist/lib/e2e/poll.d.mts +1 -1
- package/dist/lib/e2e/release.d.mts +1 -0
- package/dist/lib/e2e/release.mjs +16 -32
- package/dist/lib/e2e/tarball.mjs +2 -34
- package/dist/lib/e2e/testHarness.d.mts +36 -4
- package/dist/lib/e2e/testHarness.mjs +216 -128
- package/dist/lib/e2e/utils.d.mts +1 -0
- package/dist/lib/e2e/utils.mjs +15 -0
- package/dist/runtime/client/client.d.ts +35 -0
- package/dist/runtime/client/client.js +35 -0
- package/dist/runtime/client/navigation.d.ts +49 -0
- package/dist/runtime/client/navigation.js +80 -31
- package/dist/runtime/entries/clientSSR.d.ts +1 -0
- package/dist/runtime/entries/clientSSR.js +3 -0
- package/dist/runtime/entries/router.d.ts +1 -0
- package/dist/runtime/entries/routerClient.d.ts +1 -0
- package/dist/runtime/entries/routerClient.js +1 -0
- package/dist/runtime/entries/worker.d.ts +2 -0
- package/dist/runtime/entries/worker.js +2 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.d.ts +6 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.js +6 -0
- package/dist/runtime/lib/db/SqliteDurableObject.d.ts +2 -2
- package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
- package/dist/runtime/lib/db/createDb.d.ts +1 -2
- package/dist/runtime/lib/db/createDb.js +4 -0
- package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +13 -3
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +35 -21
- package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +9 -2
- package/dist/runtime/lib/db/typeInference/database.d.ts +16 -2
- package/dist/runtime/lib/db/typeInference/typetests/alterTable.typetest.js +80 -5
- package/dist/runtime/lib/db/typeInference/typetests/createTable.typetest.js +104 -2
- package/dist/runtime/lib/db/typeInference/typetests/testUtils.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/utils.d.ts +59 -9
- package/dist/runtime/lib/links.d.ts +18 -7
- package/dist/runtime/lib/links.js +70 -24
- package/dist/runtime/lib/links.test.js +20 -0
- package/dist/runtime/lib/manifest.d.ts +1 -1
- package/dist/runtime/lib/manifest.js +7 -4
- package/dist/runtime/lib/realtime/client.js +8 -2
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/router.d.ts +147 -33
- package/dist/runtime/lib/router.js +169 -20
- package/dist/runtime/lib/router.test.js +241 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +66 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +302 -35
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.d.ts +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.js +418 -0
- package/dist/runtime/lib/{rwContext.d.ts → types.d.ts} +1 -0
- package/dist/runtime/lib/types.js +1 -0
- package/dist/runtime/render/renderDocumentHtmlStream.d.ts +1 -1
- package/dist/runtime/render/renderToStream.d.ts +4 -2
- package/dist/runtime/render/renderToStream.js +53 -24
- package/dist/runtime/render/renderToString.d.ts +3 -1
- package/dist/runtime/requestInfo/types.d.ts +4 -1
- package/dist/runtime/requestInfo/utils.d.ts +9 -0
- package/dist/runtime/requestInfo/utils.js +44 -0
- package/dist/runtime/requestInfo/worker.js +3 -2
- package/dist/runtime/script.d.ts +1 -3
- package/dist/runtime/script.js +1 -10
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +13 -0
- package/dist/runtime/worker.d.ts +3 -1
- package/dist/runtime/worker.js +26 -0
- package/dist/scripts/debug-sync.mjs +18 -20
- package/dist/scripts/worker-run.d.mts +1 -1
- package/dist/scripts/worker-run.mjs +52 -113
- package/dist/use-synced-state/SyncStateServer.d.mts +20 -0
- package/dist/use-synced-state/SyncStateServer.mjs +124 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.mjs +109 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.js +115 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.js +115 -0
- package/dist/use-synced-state/__tests__/worker.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/worker.test.mjs +69 -0
- package/dist/use-synced-state/client.d.ts +28 -0
- package/dist/use-synced-state/client.js +39 -0
- package/dist/use-synced-state/constants.d.mts +1 -0
- package/dist/use-synced-state/constants.mjs +1 -0
- package/dist/use-synced-state/useSyncState.d.ts +20 -0
- package/dist/use-synced-state/useSyncState.js +58 -0
- package/dist/use-synced-state/useSyncedState.d.ts +20 -0
- package/dist/use-synced-state/useSyncedState.js +58 -0
- package/dist/use-synced-state/worker.d.mts +14 -0
- package/dist/use-synced-state/worker.mjs +73 -0
- package/dist/vite/buildApp.mjs +34 -2
- package/dist/vite/configPlugin.mjs +8 -14
- package/dist/vite/constants.d.mts +1 -0
- package/dist/vite/constants.mjs +1 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +1 -1
- package/dist/vite/envResolvers.d.mts +11 -0
- package/dist/vite/envResolvers.mjs +20 -0
- package/dist/vite/getViteEsbuild.mjs +2 -1
- package/dist/vite/hmrStabilityPlugin.d.mts +2 -0
- package/dist/vite/hmrStabilityPlugin.mjs +68 -0
- package/dist/vite/knownDepsResolverPlugin.d.mts +0 -6
- package/dist/vite/knownDepsResolverPlugin.mjs +1 -12
- package/dist/vite/linkerPlugin.d.mts +2 -1
- package/dist/vite/linkerPlugin.mjs +11 -3
- package/dist/vite/linkerPlugin.test.mjs +15 -0
- package/dist/vite/miniflareHMRPlugin.mjs +1 -38
- package/dist/vite/moveStaticAssetsPlugin.mjs +14 -4
- package/dist/vite/redwoodPlugin.mjs +6 -10
- package/dist/vite/runDirectivesScan.mjs +59 -14
- package/dist/vite/ssrBridgePlugin.mjs +122 -34
- package/dist/vite/ssrBridgeWrapPlugin.d.mts +2 -0
- package/dist/vite/ssrBridgeWrapPlugin.mjs +85 -0
- package/dist/vite/staleDepRetryPlugin.d.mts +2 -0
- package/dist/vite/staleDepRetryPlugin.mjs +69 -0
- package/dist/vite/statePlugin.d.mts +4 -0
- package/dist/vite/statePlugin.mjs +62 -0
- package/package.json +26 -10
- package/dist/vite/manifestPlugin.d.mts +0 -4
- package/dist/vite/manifestPlugin.mjs +0 -63
- /package/dist/runtime/lib/{rwContext.js → links.test.d.ts} +0 -0
|
@@ -4,6 +4,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
// context(justinvdm, 14 Aug 2025): `react-server-dom-webpack` uses this global
|
|
5
5
|
// to load modules, so we need to define it here before importing
|
|
6
6
|
// "react-server-dom-webpack."
|
|
7
|
+
// prettier-ignore
|
|
7
8
|
import "./setWebpackRequire";
|
|
8
9
|
import React from "react";
|
|
9
10
|
import { hydrateRoot } from "react-dom/client";
|
|
@@ -11,6 +12,7 @@ import { createFromFetch, createFromReadableStream, encodeReply, } from "react-s
|
|
|
11
12
|
import { rscStream } from "rsc-html-stream/client";
|
|
12
13
|
export { default as React } from "react";
|
|
13
14
|
export { ClientOnly } from "./ClientOnly.js";
|
|
15
|
+
export { initClientNavigation, navigate } from "./navigation.js";
|
|
14
16
|
export const fetchTransport = (transportContext) => {
|
|
15
17
|
const fetchCallServer = async (id, args) => {
|
|
16
18
|
const url = new URL(window.location.href);
|
|
@@ -48,6 +50,39 @@ export const fetchTransport = (transportContext) => {
|
|
|
48
50
|
};
|
|
49
51
|
return fetchCallServer;
|
|
50
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Initializes the React client and hydrates the RSC payload.
|
|
55
|
+
*
|
|
56
|
+
* This function sets up client-side hydration for React Server Components,
|
|
57
|
+
* making the page interactive. Call this from your client entry point.
|
|
58
|
+
*
|
|
59
|
+
* @param transport - Custom transport for server communication (defaults to fetchTransport)
|
|
60
|
+
* @param hydrateRootOptions - Options passed to React's hydrateRoot
|
|
61
|
+
* @param handleResponse - Custom response handler for navigation errors
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Basic usage
|
|
65
|
+
* import { initClient } from "rwsdk/client";
|
|
66
|
+
*
|
|
67
|
+
* initClient();
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // With client-side navigation
|
|
71
|
+
* import { initClient, initClientNavigation } from "rwsdk/client";
|
|
72
|
+
*
|
|
73
|
+
* const { handleResponse } = initClientNavigation();
|
|
74
|
+
* initClient({ handleResponse });
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // With custom React hydration options
|
|
78
|
+
* initClient({
|
|
79
|
+
* hydrateRootOptions: {
|
|
80
|
+
* onRecoverableError: (error) => {
|
|
81
|
+
* console.warn("Recoverable error:", error);
|
|
82
|
+
* },
|
|
83
|
+
* },
|
|
84
|
+
* });
|
|
85
|
+
*/
|
|
51
86
|
export const initClient = async ({ transport = fetchTransport, hydrateRootOptions, handleResponse, } = {}) => {
|
|
52
87
|
const transportContext = {
|
|
53
88
|
setRscPayload: () => { },
|
|
@@ -4,6 +4,55 @@ export interface ClientNavigationOptions {
|
|
|
4
4
|
scrollBehavior?: "auto" | "smooth" | "instant";
|
|
5
5
|
}
|
|
6
6
|
export declare function validateClickEvent(event: MouseEvent, target: HTMLElement): boolean;
|
|
7
|
+
export interface NavigateOptions {
|
|
8
|
+
history?: "push" | "replace";
|
|
9
|
+
info?: {
|
|
10
|
+
scrollToTop?: boolean;
|
|
11
|
+
scrollBehavior?: "auto" | "smooth" | "instant";
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function navigate(href: string, options?: NavigateOptions): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Initializes client-side navigation for Single Page App (SPA) behavior.
|
|
17
|
+
*
|
|
18
|
+
* Intercepts clicks on internal links and fetches page content without full-page reloads.
|
|
19
|
+
* Returns a handleResponse function to pass to initClient.
|
|
20
|
+
*
|
|
21
|
+
* @param opts.scrollToTop - Scroll to top after navigation (default: true)
|
|
22
|
+
* @param opts.scrollBehavior - How to scroll: 'instant', 'smooth', or 'auto' (default: 'instant')
|
|
23
|
+
* @param opts.onNavigate - Callback executed after history push but before RSC fetch
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Basic usage
|
|
27
|
+
* import { initClient, initClientNavigation } from "rwsdk/client";
|
|
28
|
+
*
|
|
29
|
+
* const { handleResponse } = initClientNavigation();
|
|
30
|
+
* initClient({ handleResponse });
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // With custom scroll behavior
|
|
34
|
+
* const { handleResponse } = initClientNavigation({
|
|
35
|
+
* scrollBehavior: "smooth",
|
|
36
|
+
* scrollToTop: true,
|
|
37
|
+
* });
|
|
38
|
+
* initClient({ handleResponse });
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // Preserve scroll position (e.g., for infinite scroll)
|
|
42
|
+
* const { handleResponse } = initClientNavigation({
|
|
43
|
+
* scrollToTop: false,
|
|
44
|
+
* });
|
|
45
|
+
* initClient({ handleResponse });
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // With navigation callback
|
|
49
|
+
* const { handleResponse } = initClientNavigation({
|
|
50
|
+
* onNavigate: () => {
|
|
51
|
+
* console.log("Navigating to:", window.location.href);
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
* initClient({ handleResponse });
|
|
55
|
+
*/
|
|
7
56
|
export declare function initClientNavigation(opts?: ClientNavigationOptions): {
|
|
8
57
|
handleResponse: (response: Response) => boolean;
|
|
9
58
|
};
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
function saveScrollPosition(x, y) {
|
|
2
|
-
window.history.replaceState({
|
|
3
|
-
...window.history.state,
|
|
4
|
-
scrollX: x,
|
|
5
|
-
scrollY: y,
|
|
6
|
-
}, "", window.location.href);
|
|
7
|
-
}
|
|
8
1
|
export function validateClickEvent(event, target) {
|
|
9
2
|
// should this only work for left click?
|
|
10
3
|
if (event.button !== 0) {
|
|
@@ -37,19 +30,85 @@ export function validateClickEvent(event, target) {
|
|
|
37
30
|
}
|
|
38
31
|
return true;
|
|
39
32
|
}
|
|
33
|
+
let IS_CLIENT_NAVIGATION = false;
|
|
34
|
+
export async function navigate(href, options = { history: "push" }) {
|
|
35
|
+
if (!IS_CLIENT_NAVIGATION) {
|
|
36
|
+
window.location.href = href;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
saveScrollPosition(window.scrollX, window.scrollY);
|
|
40
|
+
const url = window.location.origin + href;
|
|
41
|
+
if (options.history === "push") {
|
|
42
|
+
window.history.pushState({ path: href }, "", url);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
window.history.replaceState({ path: href }, "", url);
|
|
46
|
+
}
|
|
47
|
+
// @ts-expect-error
|
|
48
|
+
await globalThis.__rsc_callServer();
|
|
49
|
+
const scrollToTop = options.info?.scrollToTop ?? true;
|
|
50
|
+
const scrollBehavior = options.info?.scrollBehavior ?? "instant";
|
|
51
|
+
if (scrollToTop && history.scrollRestoration === "auto") {
|
|
52
|
+
window.scrollTo({
|
|
53
|
+
top: 0,
|
|
54
|
+
left: 0,
|
|
55
|
+
behavior: scrollBehavior,
|
|
56
|
+
});
|
|
57
|
+
saveScrollPosition(0, 0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function saveScrollPosition(x, y) {
|
|
61
|
+
window.history.replaceState({
|
|
62
|
+
...window.history.state,
|
|
63
|
+
scrollX: x,
|
|
64
|
+
scrollY: y,
|
|
65
|
+
}, "", window.location.href);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Initializes client-side navigation for Single Page App (SPA) behavior.
|
|
69
|
+
*
|
|
70
|
+
* Intercepts clicks on internal links and fetches page content without full-page reloads.
|
|
71
|
+
* Returns a handleResponse function to pass to initClient.
|
|
72
|
+
*
|
|
73
|
+
* @param opts.scrollToTop - Scroll to top after navigation (default: true)
|
|
74
|
+
* @param opts.scrollBehavior - How to scroll: 'instant', 'smooth', or 'auto' (default: 'instant')
|
|
75
|
+
* @param opts.onNavigate - Callback executed after history push but before RSC fetch
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Basic usage
|
|
79
|
+
* import { initClient, initClientNavigation } from "rwsdk/client";
|
|
80
|
+
*
|
|
81
|
+
* const { handleResponse } = initClientNavigation();
|
|
82
|
+
* initClient({ handleResponse });
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // With custom scroll behavior
|
|
86
|
+
* const { handleResponse } = initClientNavigation({
|
|
87
|
+
* scrollBehavior: "smooth",
|
|
88
|
+
* scrollToTop: true,
|
|
89
|
+
* });
|
|
90
|
+
* initClient({ handleResponse });
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Preserve scroll position (e.g., for infinite scroll)
|
|
94
|
+
* const { handleResponse } = initClientNavigation({
|
|
95
|
+
* scrollToTop: false,
|
|
96
|
+
* });
|
|
97
|
+
* initClient({ handleResponse });
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // With navigation callback
|
|
101
|
+
* const { handleResponse } = initClientNavigation({
|
|
102
|
+
* onNavigate: () => {
|
|
103
|
+
* console.log("Navigating to:", window.location.href);
|
|
104
|
+
* },
|
|
105
|
+
* });
|
|
106
|
+
* initClient({ handleResponse });
|
|
107
|
+
*/
|
|
40
108
|
export function initClientNavigation(opts = {}) {
|
|
41
|
-
|
|
42
|
-
onNavigate: async function onNavigate() {
|
|
43
|
-
// @ts-expect-error
|
|
44
|
-
await globalThis.__rsc_callServer();
|
|
45
|
-
},
|
|
46
|
-
scrollToTop: true,
|
|
47
|
-
scrollBehavior: "instant",
|
|
48
|
-
...opts,
|
|
49
|
-
};
|
|
109
|
+
IS_CLIENT_NAVIGATION = true;
|
|
50
110
|
history.scrollRestoration = "auto";
|
|
51
111
|
document.addEventListener("click", async function handleClickEvent(event) {
|
|
52
|
-
// Prevent default navigation
|
|
53
112
|
if (!validateClickEvent(event, event.target)) {
|
|
54
113
|
return;
|
|
55
114
|
}
|
|
@@ -57,28 +116,18 @@ export function initClientNavigation(opts = {}) {
|
|
|
57
116
|
const el = event.target;
|
|
58
117
|
const a = el.closest("a");
|
|
59
118
|
const href = a?.getAttribute("href");
|
|
60
|
-
|
|
61
|
-
window.history.pushState({ path: href }, "", window.location.origin + href);
|
|
62
|
-
await options.onNavigate();
|
|
63
|
-
if (options.scrollToTop && history.scrollRestoration === "auto") {
|
|
64
|
-
window.scrollTo({
|
|
65
|
-
top: 0,
|
|
66
|
-
left: 0,
|
|
67
|
-
behavior: options.scrollBehavior,
|
|
68
|
-
});
|
|
69
|
-
saveScrollPosition(0, 0);
|
|
70
|
-
}
|
|
71
|
-
history.scrollRestoration = "auto";
|
|
119
|
+
navigate(href);
|
|
72
120
|
}, true);
|
|
73
121
|
window.addEventListener("popstate", async function handlePopState() {
|
|
74
|
-
|
|
75
|
-
await
|
|
122
|
+
// @ts-expect-error
|
|
123
|
+
await globalThis.__rsc_callServer();
|
|
76
124
|
});
|
|
77
125
|
// Return a handleResponse function for use with initClient
|
|
78
126
|
return {
|
|
79
127
|
handleResponse: function handleResponse(response) {
|
|
80
128
|
if (!response.ok) {
|
|
81
129
|
// Redirect to the current page (window.location) to show the error
|
|
130
|
+
// This means the page that produced the error is called twice.
|
|
82
131
|
window.location.href = window.location.href;
|
|
83
132
|
return false;
|
|
84
133
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineLinks } from "../lib/links.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineLinks } from "../lib/links.js";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import "./types/worker";
|
|
2
2
|
export * from "../error";
|
|
3
|
+
export * from "../lib/types";
|
|
3
4
|
export * from "../lib/utils";
|
|
4
5
|
export * from "../register/worker";
|
|
5
6
|
export * from "../render/renderToStream";
|
|
6
7
|
export * from "../render/renderToString";
|
|
7
8
|
export * from "../requestInfo/types";
|
|
9
|
+
export * from "../requestInfo/utils";
|
|
8
10
|
export * from "../requestInfo/worker";
|
|
9
11
|
export * from "../script";
|
|
10
12
|
export * from "../worker";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import "./types/worker";
|
|
2
2
|
export * from "../error";
|
|
3
|
+
export * from "../lib/types";
|
|
3
4
|
export * from "../lib/utils";
|
|
4
5
|
export * from "../register/worker";
|
|
5
6
|
export * from "../render/renderToStream";
|
|
6
7
|
export * from "../render/renderToString";
|
|
7
8
|
export * from "../requestInfo/types";
|
|
9
|
+
export * from "../requestInfo/utils";
|
|
8
10
|
export * from "../requestInfo/worker";
|
|
9
11
|
export * from "../script";
|
|
10
12
|
export * from "../worker";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation of the virtual:use-client-lookup.js module for tests.
|
|
3
|
+
* This provides an empty lookup object since tests don't need to actually
|
|
4
|
+
* load client modules - they use dependency injection for React hooks.
|
|
5
|
+
*/
|
|
6
|
+
export declare const useClientLookup: Record<string, () => Promise<any>>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation of the virtual:use-client-lookup.js module for tests.
|
|
3
|
+
* This provides an empty lookup object since tests don't need to actually
|
|
4
|
+
* load client modules - they use dependency injection for React hooks.
|
|
5
|
+
*/
|
|
6
|
+
export const useClientLookup = {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { DurableObject } from "cloudflare:workers";
|
|
2
|
-
import { Kysely, QueryResult } from "kysely";
|
|
2
|
+
import { Kysely, KyselyPlugin, QueryResult } from "kysely";
|
|
3
3
|
export declare class SqliteDurableObject<T = any> extends DurableObject {
|
|
4
4
|
migrations: Record<string, any>;
|
|
5
5
|
kysely: Kysely<T>;
|
|
6
6
|
private initialized;
|
|
7
7
|
private migrationTableName;
|
|
8
|
-
constructor(ctx: DurableObjectState, env: any, migrations: Record<string, any>, migrationTableName?: string);
|
|
8
|
+
constructor(ctx: DurableObjectState, env: any, migrations: Record<string, any>, migrationTableName?: string, plugins?: KyselyPlugin[]);
|
|
9
9
|
initialize(): Promise<void>;
|
|
10
10
|
kyselyExecuteQuery<R>(compiledQuery: {
|
|
11
11
|
sql: string;
|
|
@@ -6,14 +6,14 @@ import { createMigrator } from "./index.js";
|
|
|
6
6
|
const log = debug("sdk:do-db");
|
|
7
7
|
// Base class for Durable Objects that need Kysely database access
|
|
8
8
|
export class SqliteDurableObject extends DurableObject {
|
|
9
|
-
constructor(ctx, env, migrations, migrationTableName = "__migrations") {
|
|
9
|
+
constructor(ctx, env, migrations, migrationTableName = "__migrations", plugins = [new ParseJSONResultsPlugin()]) {
|
|
10
10
|
super(ctx, env);
|
|
11
11
|
this.initialized = false;
|
|
12
12
|
this.migrations = migrations;
|
|
13
13
|
this.migrationTableName = migrationTableName;
|
|
14
14
|
this.kysely = new Kysely({
|
|
15
15
|
dialect: new DODialect({ ctx }),
|
|
16
|
-
plugins:
|
|
16
|
+
plugins: plugins,
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
async initialize() {
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { Kysely } from "kysely";
|
|
2
|
-
|
|
3
|
-
export declare function createDb<T>(durableObjectBinding: DurableObjectNamespace<SqliteDurableObject>, name?: string): Kysely<T>;
|
|
2
|
+
export declare function createDb<DatabaseType>(durableObjectBinding: DurableObjectNamespace<any>, name?: string): Kysely<DatabaseType>;
|
|
@@ -5,6 +5,10 @@ export function createDb(durableObjectBinding, name = "main") {
|
|
|
5
5
|
dialect: new DOWorkerDialect({
|
|
6
6
|
kyselyExecuteQuery: (...args) => {
|
|
7
7
|
const durableObjectId = durableObjectBinding.idFromName(name);
|
|
8
|
+
// context(justinvdm, 2 Oct 2025): First prize would be a type parameter
|
|
9
|
+
// for the durable object and then use it for `durableObjectBinding`'s
|
|
10
|
+
// type, rather than casting like this. However, that would prevent
|
|
11
|
+
// users from being able to do createDb<InferredDbType> then though.
|
|
8
12
|
const stub = durableObjectBinding.get(durableObjectId);
|
|
9
13
|
stub.initialize();
|
|
10
14
|
return stub.kyselyExecuteQuery(...args);
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { CheckConstraintNode, Expression, ForeignKeyConstraintBuilder, PrimaryKeyConstraintNode, sql, UniqueConstraintNode } from "kysely";
|
|
2
2
|
import { AddColumnOp, AlterColumnOp, AlterOperation, DropColumnOp, ExecutedBuilder, ModifyColumnOp, RenameColumnOp, SqlToTsType } from "../utils";
|
|
3
3
|
import { AlterColumnBuilderCallback } from "./alterColumn";
|
|
4
|
-
import { ColumnDefinitionBuilder } from "./columnDefinition";
|
|
4
|
+
import { ColumnDefinitionBuilder, ColumnDescriptor } from "./columnDefinition";
|
|
5
5
|
type DataTypeExpression = string | typeof sql;
|
|
6
|
+
type InitialDescriptor<TType> = {
|
|
7
|
+
tsType: TType;
|
|
8
|
+
isNullable: true;
|
|
9
|
+
hasDefault: false;
|
|
10
|
+
isAutoIncrement: false;
|
|
11
|
+
};
|
|
6
12
|
interface CheckConstraintBuilder {
|
|
7
13
|
$call<T>(func: (qb: this) => T): T;
|
|
8
14
|
toOperationNode(): CheckConstraintNode;
|
|
@@ -31,14 +37,18 @@ export interface AlterTableBuilder<TName extends string, TOps extends AlterOpera
|
|
|
31
37
|
readonly __renamedFrom: TName;
|
|
32
38
|
};
|
|
33
39
|
setSchema(newSchema: string): AlterTableBuilder<TName, TOps>;
|
|
34
|
-
addColumn<K extends string, T extends DataTypeExpression>(name: K, type: T
|
|
40
|
+
addColumn<K extends string, T extends DataTypeExpression>(name: K, type: T): AlterTableBuilder<TName, [
|
|
41
|
+
...TOps,
|
|
42
|
+
AddColumnOp<K, T, InitialDescriptor<SqlToTsType<T>>>
|
|
43
|
+
]>;
|
|
44
|
+
addColumn<K extends string, T extends DataTypeExpression, TDescriptor extends ColumnDescriptor>(name: K, type: T, build: (col: ColumnDefinitionBuilder<InitialDescriptor<SqlToTsType<T>>>) => ColumnDefinitionBuilder<TDescriptor>): AlterTableBuilder<TName, [...TOps, AddColumnOp<K, T, TDescriptor>]>;
|
|
35
45
|
dropColumn<K extends string>(name: K): AlterTableBuilder<TName, [...TOps, DropColumnOp<K>]>;
|
|
36
46
|
renameColumn<KFrom extends string, KTo extends string>(from: KFrom, to: KTo): AlterTableBuilder<TName, [...TOps, RenameColumnOp<KFrom, KTo>]>;
|
|
37
47
|
alterColumn<K extends string, const TCallback extends AlterColumnBuilderCallback>(column: K, alteration: TCallback): AlterTableBuilder<TName, [
|
|
38
48
|
...TOps,
|
|
39
49
|
AlterColumnOp<K, ReturnType<TCallback>["__alteration"]>
|
|
40
50
|
]>;
|
|
41
|
-
modifyColumn<K extends string, T extends DataTypeExpression>(column: K, type: T, build?: (col: ColumnDefinitionBuilder<SqlToTsType<T
|
|
51
|
+
modifyColumn<K extends string, T extends DataTypeExpression, TDescriptor extends ColumnDescriptor>(column: K, type: T, build?: (col: ColumnDefinitionBuilder<InitialDescriptor<SqlToTsType<T>>>) => ColumnDefinitionBuilder<TDescriptor>): AlterTableBuilder<TName, [...TOps, ModifyColumnOp<K, T, TDescriptor>]>;
|
|
42
52
|
addUniqueConstraint(constraintName: string, columns: string[], build?: (builder: UniqueConstraintBuilder) => UniqueConstraintBuilder): AlterTableBuilder<TName, TOps>;
|
|
43
53
|
addPrimaryKeyConstraint(constraintName: string, columns: string[], build?: (builder: PrimaryKeyConstraintBuilder) => PrimaryKeyConstraintBuilder): AlterTableBuilder<TName, TOps>;
|
|
44
54
|
addCheckConstraint(constraintName: string, checkExpression: Expression<any>, build?: (builder: CheckConstraintBuilder) => CheckConstraintBuilder): AlterTableBuilder<TName, TOps>;
|
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
import { ColumnDefinitionNode, Expression, sql } from "kysely";
|
|
2
|
-
type DefaultValueExpression = string | number | boolean | null | typeof sql
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
type DefaultValueExpression = string | number | boolean | null | ReturnType<typeof sql>;
|
|
3
|
+
export type ColumnDescriptor = {
|
|
4
|
+
tsType: any;
|
|
5
|
+
isNullable: boolean;
|
|
6
|
+
hasDefault: boolean;
|
|
7
|
+
isAutoIncrement: boolean;
|
|
8
|
+
};
|
|
9
|
+
export interface ColumnDefinitionBuilder<TDescriptor extends ColumnDescriptor> {
|
|
10
|
+
autoIncrement(): ColumnDefinitionBuilder<{
|
|
11
|
+
[K in keyof TDescriptor]: K extends "isAutoIncrement" ? true : TDescriptor[K];
|
|
12
|
+
}>;
|
|
13
|
+
identity(): ColumnDefinitionBuilder<TDescriptor>;
|
|
14
|
+
primaryKey(): ColumnDefinitionBuilder<{
|
|
15
|
+
[K in keyof TDescriptor]: K extends "isNullable" ? false : TDescriptor[K];
|
|
16
|
+
}>;
|
|
17
|
+
references(ref: string): ColumnDefinitionBuilder<TDescriptor>;
|
|
18
|
+
onDelete(onDelete: "no action" | "restrict" | "cascade" | "set null" | "set default"): ColumnDefinitionBuilder<TDescriptor>;
|
|
19
|
+
onUpdate(onUpdate: "no action" | "restrict" | "cascade" | "set null" | "set default"): ColumnDefinitionBuilder<TDescriptor>;
|
|
20
|
+
unique(): ColumnDefinitionBuilder<TDescriptor>;
|
|
21
|
+
notNull(): ColumnDefinitionBuilder<{
|
|
22
|
+
[K in keyof TDescriptor]: K extends "isNullable" ? false : TDescriptor[K];
|
|
23
|
+
}>;
|
|
24
|
+
unsigned(): ColumnDefinitionBuilder<TDescriptor>;
|
|
25
|
+
defaultTo(value: DefaultValueExpression): ColumnDefinitionBuilder<{
|
|
26
|
+
[K in keyof TDescriptor]: K extends "isNullable" ? false : K extends "hasDefault" ? true : TDescriptor[K];
|
|
27
|
+
}>;
|
|
28
|
+
check(expression: Expression<any>): ColumnDefinitionBuilder<TDescriptor>;
|
|
29
|
+
generatedAlwaysAs(expression: Expression<any>): ColumnDefinitionBuilder<TDescriptor>;
|
|
30
|
+
generatedAlwaysAsIdentity(): ColumnDefinitionBuilder<TDescriptor>;
|
|
31
|
+
generatedByDefaultAsIdentity(): ColumnDefinitionBuilder<TDescriptor>;
|
|
32
|
+
stored(): ColumnDefinitionBuilder<TDescriptor>;
|
|
33
|
+
modifyFront(modifier: Expression<any>): ColumnDefinitionBuilder<TDescriptor>;
|
|
34
|
+
nullsNotDistinct(): ColumnDefinitionBuilder<TDescriptor>;
|
|
35
|
+
ifNotExists(): ColumnDefinitionBuilder<TDescriptor>;
|
|
36
|
+
modifyEnd(modifier: Expression<any>): ColumnDefinitionBuilder<TDescriptor>;
|
|
23
37
|
$call<T>(func: (qb: this) => T): T;
|
|
24
38
|
toOperationNode(): ColumnDefinitionNode;
|
|
25
39
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CheckConstraintNode, CompiledQuery, CreateTableNode, Expression, ForeignKeyConstraintBuilder, PrimaryKeyConstraintNode, UniqueConstraintNode } from "kysely";
|
|
2
2
|
import { ExecutedBuilder, Prettify, SqlToTsType } from "../utils";
|
|
3
|
-
import { ColumnDefinitionBuilder } from "./columnDefinition";
|
|
3
|
+
import { ColumnDefinitionBuilder, ColumnDescriptor } from "./columnDefinition";
|
|
4
4
|
interface CheckConstraintBuilder {
|
|
5
5
|
$call<T>(func: (qb: this) => T): T;
|
|
6
6
|
toOperationNode(): CheckConstraintNode;
|
|
@@ -22,13 +22,20 @@ interface PrimaryKeyConstraintBuilder {
|
|
|
22
22
|
$call<T>(func: (qb: this) => T): T;
|
|
23
23
|
toOperationNode(): PrimaryKeyConstraintNode;
|
|
24
24
|
}
|
|
25
|
+
type InitialDescriptor<TType> = {
|
|
26
|
+
tsType: TType;
|
|
27
|
+
isNullable: true;
|
|
28
|
+
hasDefault: false;
|
|
29
|
+
isAutoIncrement: false;
|
|
30
|
+
};
|
|
25
31
|
export interface CreateTableBuilder<TName extends string, TSchema extends Record<string, any> = {}> {
|
|
26
32
|
readonly __tableName: TName;
|
|
27
33
|
readonly __addedColumns: TSchema;
|
|
28
34
|
temporary(): CreateTableBuilder<TName, TSchema>;
|
|
29
35
|
onCommit(onCommit: "preserve rows" | "delete rows" | "drop"): CreateTableBuilder<TName, TSchema>;
|
|
30
36
|
ifNotExists(): CreateTableBuilder<TName, TSchema>;
|
|
31
|
-
addColumn<K extends string, T extends string>(name: K, type: T
|
|
37
|
+
addColumn<K extends string, T extends string>(name: K, type: T): CreateTableBuilder<TName, Prettify<(TSchema extends Record<string, any> ? TSchema : {}) & Record<K, InitialDescriptor<SqlToTsType<T>>>>>;
|
|
38
|
+
addColumn<K extends string, T extends string, TDescriptor extends ColumnDescriptor>(name: K, type: T, build: (col: ColumnDefinitionBuilder<InitialDescriptor<SqlToTsType<T>>>) => ColumnDefinitionBuilder<TDescriptor>): CreateTableBuilder<TName, Prettify<(TSchema extends Record<string, any> ? TSchema : {}) & Record<K, TDescriptor>>>;
|
|
32
39
|
addUniqueConstraint(constraintName: string, columns: (keyof TSchema)[], build?: (builder: UniqueConstraintBuilder) => UniqueConstraintBuilder): CreateTableBuilder<TName, TSchema>;
|
|
33
40
|
addPrimaryKeyConstraint(constraintName: string, columns: (keyof TSchema)[], build?: (builder: PrimaryKeyConstraintBuilder) => PrimaryKeyConstraintBuilder): CreateTableBuilder<TName, TSchema>;
|
|
34
41
|
addCheckConstraint(constraintName: string, checkExpression: Expression<any>, build?: (builder: CheckConstraintBuilder) => CheckConstraintBuilder): CreateTableBuilder<TName, TSchema>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Kysely } from "kysely";
|
|
1
|
+
import { Generated, Kysely } from "kysely";
|
|
2
2
|
import { AlterTableBuilder } from "./builders/alterTable";
|
|
3
3
|
import { CreateTableBuilder } from "./builders/createTable";
|
|
4
4
|
import { DropTableBuilder } from "./builders/dropTable";
|
|
5
5
|
import { SchemaBuilder } from "./builders/schema";
|
|
6
6
|
import { ExecutedBuilder, Prettify, ProcessAlteredTable, UnionToTuple } from "./utils";
|
|
7
|
+
import { ColumnDescriptor } from "./builders/columnDefinition";
|
|
7
8
|
export interface InferenceBuilder {
|
|
8
9
|
schema: SchemaBuilder;
|
|
9
10
|
}
|
|
@@ -23,5 +24,18 @@ type ApplyBuilders<TSchema, TBuildersTuple> = TBuildersTuple extends [
|
|
|
23
24
|
...infer TRest
|
|
24
25
|
] ? ApplyBuilders<ApplyBuilder<TSchema, THead>, TRest> : TSchema;
|
|
25
26
|
type ProcessMigrations<TMigrations extends Migrations, TKeys, TSchema = {}> = TKeys extends [infer THeadKey, ...infer TRestKeys] ? THeadKey extends keyof TMigrations ? ProcessMigrations<TMigrations, TRestKeys, ApplyBuilders<TSchema, UnionToTuple<BuildersFromMigration<TMigrations[THeadKey]>>>> : TSchema : TSchema;
|
|
26
|
-
|
|
27
|
+
type TableToSelectType<TTable> = Prettify<{
|
|
28
|
+
[K in keyof TTable]: TTable[K] extends ColumnDescriptor ? TTable[K]["isNullable"] extends true ? TTable[K]["tsType"] | null : TTable[K]["tsType"] : TTable[K];
|
|
29
|
+
}>;
|
|
30
|
+
type TableToKyselySchema<TTable> = Prettify<{
|
|
31
|
+
[K in keyof TTable]: TTable[K] extends ColumnDescriptor ? TTable[K]["hasDefault"] extends true ? Generated<TTable[K]["isNullable"] extends true ? TTable[K]["tsType"] | null : TTable[K]["tsType"]> : TTable[K]["isAutoIncrement"] extends true ? Generated<TTable[K]["tsType"]> : TTable[K]["isNullable"] extends true ? TTable[K]["tsType"] | null : TTable[K]["tsType"] : TTable[K];
|
|
32
|
+
}>;
|
|
33
|
+
type DatabaseWithDescriptors<TMigrations extends Migrations = Migrations> = ProcessMigrations<TMigrations, UnionToTuple<keyof TMigrations>>;
|
|
34
|
+
export type Database<TMigrations extends Migrations = Migrations> = Prettify<{
|
|
35
|
+
[K in keyof DatabaseWithDescriptors<TMigrations>]: TableToSelectType<DatabaseWithDescriptors<TMigrations>[K]>;
|
|
36
|
+
} & {
|
|
37
|
+
__kyselySchema: {
|
|
38
|
+
[K in keyof DatabaseWithDescriptors<TMigrations>]: TableToKyselySchema<DatabaseWithDescriptors<TMigrations>[K]>;
|
|
39
|
+
};
|
|
40
|
+
}>;
|
|
27
41
|
export {};
|