modelence 0.23.1 → 0.24.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-3KUADF4A.js +41 -0
- package/dist/chunk-3KUADF4A.js.map +1 -0
- package/dist/chunk-63RBLFRJ.js +4 -0
- package/dist/chunk-63RBLFRJ.js.map +1 -0
- package/dist/chunk-ACX7KY6E.js +3 -0
- package/dist/{chunk-WDY7BYXR.js.map → chunk-ACX7KY6E.js.map} +1 -1
- package/dist/chunk-CHBJAOMP.js +2 -0
- package/dist/chunk-CHBJAOMP.js.map +1 -0
- package/dist/{chunk-UJ2WYHH7.js → chunk-NPBIRXLC.js} +2 -2
- package/dist/{chunk-UJ2WYHH7.js.map → chunk-NPBIRXLC.js.map} +1 -1
- package/dist/chunk-PPPB2U34.js +2 -0
- package/dist/chunk-PPPB2U34.js.map +1 -0
- package/dist/chunk-ZCIM5A5S.js +3 -0
- package/dist/chunk-ZCIM5A5S.js.map +1 -0
- package/dist/client.d.ts +120 -2
- package/dist/client.js +1 -1
- package/dist/{package-YDKHBRBH.js → package-D62UBES3.js} +2 -2
- package/dist/{package-YDKHBRBH.js.map → package-D62UBES3.js.map} +1 -1
- package/dist/{render-OM7ZJWZA.js → render-FZAHNIJB.js} +2 -2
- package/dist/{render-OM7ZJWZA.js.map → render-FZAHNIJB.js.map} +1 -1
- package/dist/renderApp-DZBN6IKT.js +2 -0
- package/dist/{renderApp-MD5O44UP.js.map → renderApp-DZBN6IKT.js.map} +1 -1
- package/dist/server-TGEMYLAH.js +2 -0
- package/dist/{server-GHQ5XNNQ.js.map → server-TGEMYLAH.js.map} +1 -1
- package/dist/server.d.ts +81 -2
- package/dist/server.js +1 -1
- package/dist/transport-N3EV2QPS.js +2 -0
- package/dist/{transport-VKGH6BY6.js.map → transport-N3EV2QPS.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-4I4BI7KD.js +0 -2
- package/dist/chunk-4I4BI7KD.js.map +0 -1
- package/dist/chunk-KDOTVIEY.js +0 -4
- package/dist/chunk-KDOTVIEY.js.map +0 -1
- package/dist/chunk-KFTT3M45.js +0 -3
- package/dist/chunk-KFTT3M45.js.map +0 -1
- package/dist/chunk-LCXJNLNK.js +0 -41
- package/dist/chunk-LCXJNLNK.js.map +0 -1
- package/dist/chunk-W4RFIS5E.js +0 -2
- package/dist/chunk-W4RFIS5E.js.map +0 -1
- package/dist/chunk-WDY7BYXR.js +0 -3
- package/dist/renderApp-MD5O44UP.js +0 -2
- package/dist/server-GHQ5XNNQ.js +0 -2
- package/dist/transport-VKGH6BY6.js +0 -2
package/dist/client.d.ts
CHANGED
|
@@ -16,8 +16,16 @@ interface ClientConfig {
|
|
|
16
16
|
* Opens a URL for OAuth redirects. React Native must use
|
|
17
17
|
* `(url) => Linking.openURL(url)` — WebView is not supported.
|
|
18
18
|
* Defaults to `window.location.href` when not provided.
|
|
19
|
+
*
|
|
20
|
+
* A web client that opens the flow in a popup should return the window
|
|
21
|
+
* `window.open` gave it: `(url) => window.open(url)`. With that reference the
|
|
22
|
+
* callback page in the popup can obtain the sign-in verifier from this page
|
|
23
|
+
* directly, which is what makes `loginWithOAuth` work when the app itself
|
|
24
|
+
* runs inside a cross-origin iframe and the popup's storage is partitioned
|
|
25
|
+
* away from it. Any other return value (including the `Promise` from
|
|
26
|
+
* `Linking.openURL`) is ignored.
|
|
19
27
|
*/
|
|
20
|
-
openUrl?: (url: string) =>
|
|
28
|
+
openUrl?: (url: string) => unknown;
|
|
21
29
|
/**
|
|
22
30
|
* Credentials mode for method-call requests. Defaults to `'include'`, which
|
|
23
31
|
* browser apps need for the cookie-based flows (password reset, magic link).
|
|
@@ -599,19 +607,111 @@ declare function resetPassword(options: {
|
|
|
599
607
|
token?: string;
|
|
600
608
|
password: string;
|
|
601
609
|
}): Promise<void>;
|
|
610
|
+
/**
|
|
611
|
+
* Start an OAuth sign-in.
|
|
612
|
+
*
|
|
613
|
+
* On the web this navigates to the provider and the flow finishes on its own —
|
|
614
|
+
* the session cookie is set and the browser lands back on your site.
|
|
615
|
+
*
|
|
616
|
+
* Pass `redirectUri` to run the native flow: the device browser opens the
|
|
617
|
+
* provider, and when the flow completes Modelence redirects back to that deep
|
|
618
|
+
* link with a single-use `code` query parameter. Hand that code to
|
|
619
|
+
* {@link loginWithOAuth} to finish signing in. The redirect target must be
|
|
620
|
+
* listed in the server's `auth.mobile.redirectUrls`, otherwise the request is
|
|
621
|
+
* rejected before the provider is ever reached.
|
|
622
|
+
*
|
|
623
|
+
* The native flow additionally binds the sign-in to this device: a verifier is
|
|
624
|
+
* held in memory here and replayed by `loginWithOAuth`, so a `code` delivered
|
|
625
|
+
* to the app from outside this flow cannot be redeemed.
|
|
626
|
+
*
|
|
627
|
+
* @example Web
|
|
628
|
+
* ```ts
|
|
629
|
+
* await signInWithOAuth({ provider: 'google' });
|
|
630
|
+
* ```
|
|
631
|
+
*
|
|
632
|
+
* @example React Native
|
|
633
|
+
* ```ts
|
|
634
|
+
* import { parseDeepLinkParams } from 'modelence/client';
|
|
635
|
+
*
|
|
636
|
+
* await signInWithOAuth({ provider: 'google', redirectUri: 'myapp://auth' });
|
|
637
|
+
*
|
|
638
|
+
* Linking.addEventListener('url', async ({ url }) => {
|
|
639
|
+
* const { code } = parseDeepLinkParams(url);
|
|
640
|
+
* if (code) await loginWithOAuth({ code });
|
|
641
|
+
* });
|
|
642
|
+
* ```
|
|
643
|
+
* @param options.provider - The OAuth provider to sign in with ('google' or 'github').
|
|
644
|
+
* @param options.redirectUri - Deep link to return to. Required on React Native.
|
|
645
|
+
*/
|
|
646
|
+
declare function signInWithOAuth(options: {
|
|
647
|
+
provider: OAuthProvider;
|
|
648
|
+
redirectUri?: string;
|
|
649
|
+
}): Promise<void>;
|
|
650
|
+
/**
|
|
651
|
+
* Complete a native OAuth sign-in with the code from the deep link.
|
|
652
|
+
*
|
|
653
|
+
* Exchanges the single-use code that {@link signInWithOAuth} delivered to your
|
|
654
|
+
* app's deep link for a session, stores the auth token, and returns the
|
|
655
|
+
* signed-in user. Codes are valid for one minute and can only be redeemed once.
|
|
656
|
+
*
|
|
657
|
+
* Pairs with `signInWithOAuth({ provider, redirectUri })` — the flow that hands
|
|
658
|
+
* a code back to your app. It works on native and under Expo Web, where the
|
|
659
|
+
* verifier is kept in `sessionStorage` so it survives the navigation to the
|
|
660
|
+
* provider. When the flow ran in a popup whose `openUrl` returned the window
|
|
661
|
+
* it opened, the verifier is fetched from the opening page when this page's
|
|
662
|
+
* storage has none, so it also works when the app is embedded in a
|
|
663
|
+
* cross-origin iframe. A plain web app
|
|
664
|
+
* that calls `signInWithOAuth({ provider })` with no `redirectUri` is signed
|
|
665
|
+
* in by a session cookie and never needs this.
|
|
666
|
+
*
|
|
667
|
+
* The verifier minted by `signInWithOAuth` is replayed here, which is what
|
|
668
|
+
* makes a code usable only by the client that started the flow. Calling this
|
|
669
|
+
* without a preceding `signInWithOAuth` — as a crafted deep link would — fails
|
|
670
|
+
* before the code is ever sent.
|
|
671
|
+
*
|
|
672
|
+
* @example
|
|
673
|
+
* ```ts
|
|
674
|
+
* const user = await loginWithOAuth({ code });
|
|
675
|
+
* ```
|
|
676
|
+
* @param options.code - The `code` query parameter from the deep link.
|
|
677
|
+
*/
|
|
678
|
+
declare function loginWithOAuth(options: {
|
|
679
|
+
code: string;
|
|
680
|
+
}): Promise<{
|
|
681
|
+
id: string;
|
|
682
|
+
handle: string;
|
|
683
|
+
roles: string[];
|
|
684
|
+
hasRole: (role: string) => boolean;
|
|
685
|
+
requireRole: (role: string) => void;
|
|
686
|
+
firstName?: string;
|
|
687
|
+
lastName?: string;
|
|
688
|
+
avatarUrl?: string;
|
|
689
|
+
} | null>;
|
|
602
690
|
/**
|
|
603
691
|
* Link an OAuth provider to the currently signed-in user's account.
|
|
604
692
|
* Redirects the browser to the OAuth provider's authorization page.
|
|
605
693
|
* The provider will redirect back and the account will be linked.
|
|
606
694
|
*
|
|
695
|
+
* Without `redirectUri` this navigates the current context and authenticates
|
|
696
|
+
* with an httpOnly cookie, so it only works where the navigation stays in the
|
|
697
|
+
* same cookie jar — a browser, or a webview that navigates in place. Clients
|
|
698
|
+
* whose `openUrl` opens an external browser (Electron, Capacitor) must pass a
|
|
699
|
+
* `redirectUri`: that flow carries a single-use nonce in the URL and does not
|
|
700
|
+
* depend on cookies.
|
|
701
|
+
*
|
|
607
702
|
* @example
|
|
608
703
|
* ```ts
|
|
609
704
|
* linkOAuthProvider({ provider: 'google' });
|
|
610
705
|
* ```
|
|
611
706
|
* @param options.provider - The OAuth provider to link ('google' or 'github').
|
|
707
|
+
* @param options.redirectUri - Deep link to return to once linking completes.
|
|
708
|
+
* Required for React Native and any client that opens URLs externally; must be
|
|
709
|
+
* listed in the server's `auth.mobile.redirectUrls`. Without it the flow ends
|
|
710
|
+
* wherever the navigation lands rather than back in the app.
|
|
612
711
|
*/
|
|
613
712
|
declare function linkOAuthProvider(options: {
|
|
614
713
|
provider: OAuthProvider;
|
|
714
|
+
redirectUri?: string;
|
|
615
715
|
}): Promise<void>;
|
|
616
716
|
/**
|
|
617
717
|
* Unlink an OAuth provider from the currently signed-in user's account.
|
|
@@ -626,6 +726,24 @@ declare function unlinkOAuthProvider(options: {
|
|
|
626
726
|
provider: OAuthProvider;
|
|
627
727
|
}): Promise<void>;
|
|
628
728
|
|
|
729
|
+
/**
|
|
730
|
+
* Deep-link query parsing that works on bare React Native.
|
|
731
|
+
*
|
|
732
|
+
* `new URL(url).searchParams` is not usable here: React Native's `URL` is a
|
|
733
|
+
* partial implementation that throws on `searchParams` access, and Expo only
|
|
734
|
+
* appears to work because it installs a polyfill. Parsing the query string
|
|
735
|
+
* directly keeps the documented callback snippet working on both.
|
|
736
|
+
*/
|
|
737
|
+
/**
|
|
738
|
+
* Reads query parameters out of a deep link such as `myapp://auth?code=abc`.
|
|
739
|
+
*
|
|
740
|
+
* Only the query component is considered — everything from the first `?` up to
|
|
741
|
+
* an optional `#` fragment. Values are percent-decoded, with `+` treated as a
|
|
742
|
+
* space to match `application/x-www-form-urlencoded`, which is how the server's
|
|
743
|
+
* `URL.searchParams.set` encodes them.
|
|
744
|
+
*/
|
|
745
|
+
declare function parseDeepLinkParams(url: string): Record<string, string>;
|
|
746
|
+
|
|
629
747
|
declare function subscribeLiveQuery<T = unknown>(method: string, args: Record<string, unknown>, onData: (data: T) => void, onError?: (error: string) => void): () => void;
|
|
630
748
|
|
|
631
749
|
declare function setWebsocketClientProvider(provider: WebsocketClientProvider | null): void;
|
|
@@ -639,4 +757,4 @@ declare function getLocalStorageSession(): any;
|
|
|
639
757
|
|
|
640
758
|
declare const AppProvider: any;
|
|
641
759
|
|
|
642
|
-
export { AppProvider, type CallMethodOptions, ClientChannel, type ClientConfig, type MethodArgs, MethodError, ModelenceQueryClient, type ModelenceQueryKey, ModelenceQueryProvider, type UserInfo, ValueType, callMethod, configureClient, connectModelenceQueryClient, createClientModule, createQueryKey, disconnectModelenceQueryClient, getConfig, getLocalStorageSession, getWebsocketClientProvider, linkOAuthProvider, loginWithMagicLink, loginWithOneTimeCode, loginWithPassword, logout, modelenceLiveQuery, modelenceMutation, modelenceQuery, renderApp, resendEmailVerification, resetPassword, sendMagicLink, sendResetPasswordToken, setWebsocketClientProvider, signupWithPassword, startWebsockets, subscribeLiveQuery, systemConfig, unlinkOAuthProvider, updateProfile, useSession, verifyEmail };
|
|
760
|
+
export { AppProvider, type CallMethodOptions, ClientChannel, type ClientConfig, type MethodArgs, MethodError, ModelenceQueryClient, type ModelenceQueryKey, ModelenceQueryProvider, type UserInfo, ValueType, callMethod, configureClient, connectModelenceQueryClient, createClientModule, createQueryKey, disconnectModelenceQueryClient, getConfig, getLocalStorageSession, getWebsocketClientProvider, linkOAuthProvider, loginWithMagicLink, loginWithOAuth, loginWithOneTimeCode, loginWithPassword, logout, modelenceLiveQuery, modelenceMutation, modelenceQuery, parseDeepLinkParams, renderApp, resendEmailVerification, resetPassword, sendMagicLink, sendResetPasswordToken, setWebsocketClientProvider, signInWithOAuth, signupWithPassword, startWebsockets, subscribeLiveQuery, systemConfig, unlinkOAuthProvider, updateProfile, useSession, verifyEmail };
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{g as AppProvider,f as ClientChannel,a as createClientModule,e as parseDeepLinkParams,d as renderApp,b as systemConfig}from'./chunk-PPPB2U34.js';export{i as ModelenceQueryClient,n as ModelenceQueryProvider,f as connectModelenceQueryClient,m as createQueryKey,h as disconnectModelenceQueryClient,d as getWebsocketClientProvider,k as modelenceLiveQuery,l as modelenceMutation,j as modelenceQuery,c as setWebsocketClientProvider,e as startWebsockets,b as subscribeLiveQuery}from'./chunk-ACX7KY6E.js';export{H as MethodError,K as callMethod,d as configureClient,b as getConfig,c as getLocalStorageSession,C as linkOAuthProvider,x as loginWithMagicLink,B as loginWithOAuth,y as loginWithOneTimeCode,q as loginWithPassword,u as logout,t as resendEmailVerification,z as resetPassword,w as sendMagicLink,v as sendResetPasswordToken,A as signInWithOAuth,p as signupWithPassword,D as unlinkOAuthProvider,r as updateProfile,o as useSession,s as verifyEmail}from'./chunk-CHBJAOMP.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=client.js.map
|
|
2
2
|
//# sourceMappingURL=client.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{m as author,i as bin,o as bugs,t as default,r as dependencies,d as description,q as devDependencies,j as engines,g as exports,h as files,p as homepage,n as license,e as main,b as name,s as peerDependencies,l as repository,k as scripts,a as type,f as types,c as version}from'./chunk-
|
|
2
|
-
//# sourceMappingURL=package-
|
|
1
|
+
export{m as author,i as bin,o as bugs,t as default,r as dependencies,d as description,q as devDependencies,j as engines,g as exports,h as files,p as homepage,n as license,e as main,b as name,s as peerDependencies,l as repository,k as scripts,a as type,f as types,c as version}from'./chunk-ZCIM5A5S.js';//# sourceMappingURL=package-D62UBES3.js.map
|
|
2
|
+
//# sourceMappingURL=package-D62UBES3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-D62UBES3.js"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {a,b,c}from'./chunk-
|
|
2
|
-
//# sourceMappingURL=render-
|
|
1
|
+
import {a,b,c}from'./chunk-NPBIRXLC.js';import'./chunk-63RBLFRJ.js';import'./chunk-UW37F3GV.js';import {a as a$1,n}from'./chunk-ACX7KY6E.js';import {m,a as a$2,n as n$1}from'./chunk-CHBJAOMP.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';import {renderToPipeableStream}from'react-dom/server';import {Writable}from'stream';import {QueryClient,dehydrate}from'@tanstack/react-query';import {jsx}from'react/jsx-runtime';var J=()=>{let r=c();return r?n$1(r.session.user):null},M=r=>{let n=c();if(n)return n.session.configs[r]?.value};function D(){m(J),a$2(M);}async function X(r){let{callContext:n$1,loadingElement:C,routesElement:S,router:u,location:x,onShellReady:E,onError:b$1}=r;D();let l=await a("_system.session.init",{},n$1),i=new QueryClient({defaultOptions:{queries:{retry:false,gcTime:0}}}),O=u?u({children:S,location:x}):S,Q=jsx(a$1,{loadingElement:C,children:jsx(n,{client:i,children:O})}),a$2=null;await new Promise((s,m)=>{b({callContext:n$1,queryClient:i,session:{user:l.user,configs:l.configs??{}}},()=>{let e=renderToPipeableStream(Q,{onShellReady(){a$2=e,E?.(),s(e);},onShellError(t){m(t);},onError(t){b$1?.(t);}});return e});});let d=null,_=s=>new Promise((m,e)=>{if(!a$2){e(new Error("SSR stream was not initialized"));return}let t=new Writable({write(o,c,I){s.write(o,N=>I(N??void 0));},final(o){try{let c=dehydrate(i);d=JSON.stringify(c);}finally{i.clear();}o(),m();}});t.on("error",o=>{s.destroy(o),e(o);}),s.on("error",e),a$2.pipe(t);});return {sessionState:JSON.stringify({session:l}),pipe:_,getQueryState:()=>{if(d===null)throw new Error("getQueryState() called before stream finished");return d}}}export{X as renderSsrTreeStream};//# sourceMappingURL=render-FZAHNIJB.js.map
|
|
2
|
+
//# sourceMappingURL=render-FZAHNIJB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ssr/render.tsx"],"names":["sessionResolver","ctx","getSsrContext","_parseSessionUser","configResolver","key","ensureSsrResolversInstalled","_setSsrSessionResolver","_setSsrConfigResolver","renderSsrTreeStream","options","callContext","loadingElement","routesElement","router","location","onShellReady","onError","sessionPayload","callInProcessMethod","queryClient","QueryClient","routedTree","tree","jsx","AppProvider","ModelenceQueryProvider","streamRef","resolve","reject","runWithSsrContext","stream","renderToPipeableStream","error","queryStateJson","pipe","destination","passthrough","Writable","chunk","_encoding","callback","err","dehydratedState","dehydrate"],"mappings":"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","file":"render-
|
|
1
|
+
{"version":3,"sources":["../src/ssr/render.tsx"],"names":["sessionResolver","ctx","getSsrContext","_parseSessionUser","configResolver","key","ensureSsrResolversInstalled","_setSsrSessionResolver","_setSsrConfigResolver","renderSsrTreeStream","options","callContext","loadingElement","routesElement","router","location","onShellReady","onError","sessionPayload","callInProcessMethod","queryClient","QueryClient","routedTree","tree","jsx","AppProvider","ModelenceQueryProvider","streamRef","resolve","reject","runWithSsrContext","stream","renderToPipeableStream","error","queryStateJson","pipe","destination","passthrough","Writable","chunk","_encoding","callback","err","dehydratedState","dehydrate"],"mappings":"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","file":"render-FZAHNIJB.js","sourcesContent":["import React from 'react';\nimport { renderToPipeableStream, type PipeableStream } from 'react-dom/server';\nimport { Writable } from 'node:stream';\nimport { QueryClient, dehydrate, type DehydratedState } from '@tanstack/react-query';\nimport { AppProvider } from '../client/AppProvider';\nimport { ModelenceQueryProvider } from '../client/queryProvider';\nimport { getSsrContext, runWithSsrContext } from './context';\nimport { callInProcessMethod } from './callInProcess';\nimport type { Context } from '../methods/types';\nimport {\n _parseSessionUser,\n _setSsrSessionResolver,\n type SessionInitPayload,\n} from '../client/session';\nimport { _setSsrConfigResolver } from '../config/client';\nimport type { ConfigKey, Configs } from '../config/types';\nimport type { SsrRouter } from '../client/renderApp';\n\nconst sessionResolver = () => {\n const ctx = getSsrContext();\n if (!ctx) {\n return null;\n }\n return _parseSessionUser(ctx.session.user);\n};\n\nconst configResolver = (key: ConfigKey) => {\n const ctx = getSsrContext();\n if (!ctx) {\n return undefined;\n }\n return ctx.session.configs[key]?.value;\n};\n\nfunction ensureSsrResolversInstalled() {\n _setSsrSessionResolver(sessionResolver);\n _setSsrConfigResolver(configResolver);\n}\n\nexport type SsrRenderOptions = {\n callContext: Context;\n loadingElement: React.ReactNode;\n routesElement: React.ReactNode;\n router?: SsrRouter;\n location?: string;\n};\n\nexport type SsrStreamHandle = {\n /** Session bootstrap payload — inline before the shell flushes. */\n sessionState: string;\n /** Pipe React's HTML into `destination`. Resolves when streaming finishes. */\n pipe: (destination: Writable) => Promise<void>;\n /** Dehydrated query state. Only call after `pipe()` resolves. */\n getQueryState: () => string;\n};\n\nexport type SsrStreamOptions = SsrRenderOptions & {\n /** Fires when the shell is flushed; caller writes prelude + state here. */\n onShellReady?: () => void;\n /** Non-fatal SSR errors (Suspense fallbacks, etc.). */\n onError?: (error: unknown) => void;\n};\n\nexport async function renderSsrTreeStream(options: SsrStreamOptions): Promise<SsrStreamHandle> {\n const { callContext, loadingElement, routesElement, router, location, onShellReady, onError } =\n options;\n\n ensureSsrResolversInstalled();\n\n const sessionPayload = await callInProcessMethod<SessionInitPayload>(\n '_system.session.init',\n {},\n callContext\n );\n\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n gcTime: 0,\n },\n },\n });\n\n const routedTree = router ? router({ children: routesElement, location }) : routesElement;\n const tree = (\n <AppProvider loadingElement={loadingElement}>\n <ModelenceQueryProvider client={queryClient}>{routedTree}</ModelenceQueryProvider>\n </AppProvider>\n );\n\n let streamRef: PipeableStream | null = null;\n // Resolves with the stream once React renders above-fallback content;\n // rejects on shell errors so the caller can fall back to a static response.\n const shellReady = new Promise<PipeableStream>((resolve, reject) => {\n // Run the render inside the SSR context so components can resolve\n // session/config/query state from the per-request scope.\n runWithSsrContext(\n {\n callContext,\n queryClient,\n session: {\n user: sessionPayload.user,\n configs: (sessionPayload.configs as Configs) ?? {},\n },\n },\n () => {\n const stream = renderToPipeableStream(tree, {\n onShellReady() {\n streamRef = stream;\n onShellReady?.();\n resolve(stream);\n },\n onShellError(error) {\n reject(error);\n },\n onError(error) {\n onError?.(error);\n },\n });\n return stream;\n }\n );\n });\n\n // Await so shell errors surface before the caller starts piping.\n await shellReady;\n\n let queryStateJson: string | null = null;\n\n const pipe = (destination: Writable): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (!streamRef) {\n reject(new Error('SSR stream was not initialized'));\n return;\n }\n\n // react-dom calls `destination.end()` when done. The caller still needs\n // to write the epilogue + query state, so wrap with a passthrough whose\n // `final()` resolves the pipe promise without closing the response.\n const passthrough = new Writable({\n write(chunk, _encoding, callback) {\n destination.write(chunk, (err) => callback(err ?? undefined));\n },\n final(callback) {\n try {\n const dehydratedState: DehydratedState = dehydrate(queryClient);\n queryStateJson = JSON.stringify(dehydratedState);\n } finally {\n queryClient.clear();\n }\n callback();\n resolve();\n },\n });\n\n passthrough.on('error', (err) => {\n destination.destroy(err);\n reject(err);\n });\n destination.on('error', reject);\n\n streamRef.pipe(passthrough);\n });\n };\n\n return {\n sessionState: JSON.stringify({ session: sessionPayload }),\n pipe,\n getQueryState: () => {\n if (queryStateJson === null) {\n throw new Error('getQueryState() called before stream finished');\n }\n return queryStateJson;\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"renderApp-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"renderApp-DZBN6IKT.js"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export{g as getCallContext,f as startServer}from'./chunk-3KUADF4A.js';import'./chunk-ZCIM5A5S.js';import'./chunk-63RBLFRJ.js';import'./chunk-VYR7VQMQ.js';import'./chunk-UW37F3GV.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server-TGEMYLAH.js.map
|
|
2
|
+
//# sourceMappingURL=server-TGEMYLAH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"server-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"server-TGEMYLAH.js"}
|
package/dist/server.d.ts
CHANGED
|
@@ -228,6 +228,8 @@ type AuthRateLimitsConfig = {
|
|
|
228
228
|
magicLink?: AuthRateLimitOverride[];
|
|
229
229
|
/** Rate limits for one-time code sign-in attempts. */
|
|
230
230
|
oneTimeCode?: AuthRateLimitOverride[];
|
|
231
|
+
/** Rate limits for redeeming a mobile OAuth exchange code. */
|
|
232
|
+
oauthExchange?: AuthRateLimitOverride[];
|
|
231
233
|
/** Per-user rate limits for profile updates. */
|
|
232
234
|
updateProfile?: AuthRateLimitOverride[];
|
|
233
235
|
};
|
|
@@ -431,8 +433,10 @@ type AuthConfig = {
|
|
|
431
433
|
* Custom handle generator. If provided, overrides the default behavior
|
|
432
434
|
* (which derives the handle from the email local-part). Receives
|
|
433
435
|
* `{ email, firstName?, lastName? }` and returns the desired handle
|
|
434
|
-
* synchronously or as a `Promise<string>`.
|
|
435
|
-
*
|
|
436
|
+
* synchronously or as a `Promise<string>`. The returned handle must contain
|
|
437
|
+
* only letters, numbers, underscores, and hyphens (matching `HANDLE_REGEX`).
|
|
438
|
+
* If the returned handle collides with an existing one, Modelence appends
|
|
439
|
+
* a numeric suffix automatically.
|
|
436
440
|
*/
|
|
437
441
|
generateHandle?: (props: GenerateHandleProps) => Promise<string> | string;
|
|
438
442
|
/** @deprecated Use {@link AuthConfig.onAfterLogin} and {@link AuthConfig.onLoginError} instead. */
|
|
@@ -501,6 +505,35 @@ type AuthConfig = {
|
|
|
501
505
|
* means disposable emails will be allowed to sign up.
|
|
502
506
|
*/
|
|
503
507
|
allowDisposableEmails?: boolean;
|
|
508
|
+
/**
|
|
509
|
+
* Settings for authenticating from a native (React Native / Expo) client.
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* ```typescript
|
|
513
|
+
* startApp({
|
|
514
|
+
* auth: {
|
|
515
|
+
* mobile: { redirectUrls: ['myapp://auth'] },
|
|
516
|
+
* },
|
|
517
|
+
* });
|
|
518
|
+
* ```
|
|
519
|
+
*/
|
|
520
|
+
mobile?: {
|
|
521
|
+
/**
|
|
522
|
+
* Deep links the OAuth callback is allowed to redirect a native app back to,
|
|
523
|
+
* e.g. `['myapp://auth']`. A sign-in request naming any other target is
|
|
524
|
+
* rejected before the user ever reaches the provider's consent screen.
|
|
525
|
+
*
|
|
526
|
+
* This is an allowlist because the redirect target decides where an auth
|
|
527
|
+
* flow ends up: without it, a crafted link could point the callback at an
|
|
528
|
+
* attacker-controlled destination. There is no implicit default — mobile
|
|
529
|
+
* OAuth stays disabled until at least one entry is configured here or via
|
|
530
|
+
* the `auth.mobile.redirectUrls` config value (the two are merged).
|
|
531
|
+
*
|
|
532
|
+
* Entries are matched on scheme, host and path; a request may add query
|
|
533
|
+
* parameters but may not change any of those three.
|
|
534
|
+
*/
|
|
535
|
+
redirectUrls?: string[];
|
|
536
|
+
};
|
|
504
537
|
};
|
|
505
538
|
|
|
506
539
|
/**
|
|
@@ -518,6 +551,8 @@ type AuthConfig = {
|
|
|
518
551
|
* startApp({
|
|
519
552
|
* security: {
|
|
520
553
|
* frameAncestors: ['https://modelence.com', 'https://app.example.com'],
|
|
554
|
+
* trustedProxies: ['loopback', 'linklocal', 'uniquelocal'],
|
|
555
|
+
* clientIpHeader: 'cf-connecting-ip',
|
|
521
556
|
* },
|
|
522
557
|
* });
|
|
523
558
|
* ```
|
|
@@ -531,6 +566,50 @@ type SecurityConfig = {
|
|
|
531
566
|
* When set, `X-Frame-Options` is omitted since it cannot express multiple origins.
|
|
532
567
|
*/
|
|
533
568
|
frameAncestors?: string[];
|
|
569
|
+
/**
|
|
570
|
+
* IP addresses or CIDR ranges of reverse proxies that are allowed to supply
|
|
571
|
+
* the client IP through `X-Forwarded-For`. This uses Express's `trust proxy`
|
|
572
|
+
* address syntax, which also supports the named ranges `loopback`,
|
|
573
|
+
* `linklocal`, and `uniquelocal`.
|
|
574
|
+
*
|
|
575
|
+
* For backward compatibility, all proxy addresses are trusted when neither
|
|
576
|
+
* this option nor `MODELENCE_TRUSTED_PROXIES` is set. Configure one of them in
|
|
577
|
+
* production so only addresses that cannot be reached directly by untrusted
|
|
578
|
+
* clients are trusted. Once configured,
|
|
579
|
+
* `connectionInfo.ip` is resolved by walking the proxy chain from the app
|
|
580
|
+
* toward the client and stopping at the first untrusted address. This keeps a
|
|
581
|
+
* caller from choosing its rate-limit identity by prepending a forged
|
|
582
|
+
* `X-Forwarded-For` value.
|
|
583
|
+
*
|
|
584
|
+
* @example
|
|
585
|
+
* ```typescript
|
|
586
|
+
* trustedProxies: ['loopback', '10.0.0.0/8']
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
trustedProxies?: string | string[];
|
|
590
|
+
/**
|
|
591
|
+
* Name of a single-value header the trusted proxy sets to the originating
|
|
592
|
+
* client IP, used instead of walking the `X-Forwarded-For` chain.
|
|
593
|
+
*
|
|
594
|
+
* Cloudflare recommends reading `CF-Connecting-IP` (or `True-Client-IP` on
|
|
595
|
+
* Enterprise plans) rather than `X-Forwarded-For`, because Cloudflare
|
|
596
|
+
* *appends* to an inbound `X-Forwarded-For` instead of overwriting it, while
|
|
597
|
+
* these headers always carry exactly one address.
|
|
598
|
+
*
|
|
599
|
+
* This header is only read when the immediate peer is a trusted proxy, so
|
|
600
|
+
* `trustedProxies` (or `MODELENCE_TRUSTED_PROXIES`) must also be configured
|
|
601
|
+
* with the proxy's addresses. Without that, a direct caller could set the
|
|
602
|
+
* header themselves and choose their own rate-limit identity. When the peer
|
|
603
|
+
* is untrusted or the header is absent, the IP falls back to the normal
|
|
604
|
+
* `trust proxy` resolution.
|
|
605
|
+
*
|
|
606
|
+
* @example
|
|
607
|
+
* ```typescript
|
|
608
|
+
* // Behind Cloudflare, with Cloudflare's published ranges trusted:
|
|
609
|
+
* clientIpHeader: 'cf-connecting-ip'
|
|
610
|
+
* ```
|
|
611
|
+
*/
|
|
612
|
+
clientIpHeader?: string;
|
|
534
613
|
};
|
|
535
614
|
|
|
536
615
|
type WebsocketConfig = {
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{m as ObjectId,k as ServerChannel,a as consumeRateLimit,c as deleteFile,j as deleteUser,i as disableUser,d as downloadFile,e as getFileUrl,b as getUploadUrl,l as sendEmail,h as startApp}from'./chunk-
|
|
1
|
+
export{m as ObjectId,k as ServerChannel,a as consumeRateLimit,c as deleteFile,j as deleteUser,i as disableUser,d as downloadFile,e as getFileUrl,b as getUploadUrl,l as sendEmail,h as startApp}from'./chunk-3KUADF4A.js';import'./chunk-ZCIM5A5S.js';export{A as LiveData,a as Module,c as Store,z as authenticate,m as clearSessionUser,C as createQuery,o as createSession,j as dbSessions,s as dbUsers,n as invalidateAllUserSessions,k as obtainSession,d as schema,p as setAuthTokenCookie,l as setSessionUser}from'./chunk-63RBLFRJ.js';import'./chunk-VYR7VQMQ.js';export{a as getConfig,h as getEnvironmentId}from'./chunk-UW37F3GV.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server.js.map
|
|
2
2
|
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {c,a}from'./chunk-NPBIRXLC.js';import'./chunk-63RBLFRJ.js';import'./chunk-UW37F3GV.js';import {J,I}from'./chunk-CHBJAOMP.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';function d(){return J(async(t,r)=>{let o=c();return o?a(t,r,o.callContext):I(t,r)})}export{d as installSsrCallMethodTransport};//# sourceMappingURL=transport-N3EV2QPS.js.map
|
|
2
|
+
//# sourceMappingURL=transport-N3EV2QPS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ssr/transport.ts"],"names":["installSsrCallMethodTransport","setCallMethodTransport","methodName","args","ssrCtx","getSsrContext","callInProcessMethod","defaultCallMethodTransport"],"mappings":"4LAcO,SAASA,CAAAA,EAA4C,CAC1D,OAAOC,CAAAA,CAAuB,MAAUC,EAAoBC,CAAAA,GAAqB,CAC/E,IAAMC,CAAAA,CAASC,CAAAA,EAAc,CAC7B,OAAKD,CAAAA,CAIEE,CAAAA,CAAuBJ,CAAAA,CAAYC,CAAAA,CAAMC,CAAAA,CAAO,WAAW,CAAA,CAHzDG,CAAAA,CAA8BL,CAAAA,CAAYC,CAAI,CAIzD,CAAC,CACH","file":"transport-
|
|
1
|
+
{"version":3,"sources":["../src/ssr/transport.ts"],"names":["installSsrCallMethodTransport","setCallMethodTransport","methodName","args","ssrCtx","getSsrContext","callInProcessMethod","defaultCallMethodTransport"],"mappings":"4LAcO,SAASA,CAAAA,EAA4C,CAC1D,OAAOC,CAAAA,CAAuB,MAAUC,EAAoBC,CAAAA,GAAqB,CAC/E,IAAMC,CAAAA,CAASC,CAAAA,EAAc,CAC7B,OAAKD,CAAAA,CAIEE,CAAAA,CAAuBJ,CAAAA,CAAYC,CAAAA,CAAMC,CAAAA,CAAO,WAAW,CAAA,CAHzDG,CAAAA,CAA8BL,CAAAA,CAAYC,CAAI,CAIzD,CAAC,CACH","file":"transport-N3EV2QPS.js","sourcesContent":["import {\n setCallMethodTransport,\n defaultCallMethodTransport,\n type MethodArgs,\n} from '../client/method';\nimport { callInProcessMethod } from './callInProcess';\nimport { getSsrContext } from './context';\n\n/**\n * Routes `callMethod` through `runMethod` in-process during an active SSR\n * render. Outside a render (e.g. server-side `callMethod` from jobs or other\n * non-render code) there is no request context, so it falls back to the\n * default HTTP transport — installing SSR must not break those call sites.\n */\nexport function installSsrCallMethodTransport(): () => void {\n return setCallMethodTransport(async <T>(methodName: string, args: MethodArgs) => {\n const ssrCtx = getSsrContext();\n if (!ssrCtx) {\n return defaultCallMethodTransport<T>(methodName, args);\n }\n\n return callInProcessMethod<T>(methodName, args, ssrCtx.callContext);\n });\n}\n"]}
|
package/package.json
CHANGED
package/dist/chunk-4I4BI7KD.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import {a,d,g as g$1,n}from'./chunk-WDY7BYXR.js';import {I as I$1,b,E,g,k}from'./chunk-W4RFIS5E.js';import R from'react';import C from'react-dom/client';import {jsx}from'react/jsx-runtime';function c(t){return {getConfig(e){return b(`${t}.${e}`)},query(e,...r){let o=r[0]??{};return {queryKey:[t,e,o],queryFn:()=>I$1(`${t}.${e}`,o)}},mutation(e){return {mutationFn:r=>I$1(`${t}.${e}`,r)}},infiniteQuery(e,r){return {queryKey:[t,e,"infinite",r(void 0)],initialPageParam:void 0,queryFn:({pageParam:o})=>I$1(`${t}.${e}`,r(o))}}}}var q=c("_system");var u=class{constructor(e,r){this.category=e,this.onMessage=r;}init(){d()?.on({category:this.category,listener:this.onMessage});}joinChannel(e){d()?.joinChannel({category:this.category,id:e});}leaveChannel(e){d()?.leaveChannel({category:this.category,id:e});}};var A="useClient"in R?R.useClient(a):a;var K="__MODELENCE_STATE__";function W(){return typeof document>"u"?false:document.getElementById(K)!==null}function H(){if(typeof document>"u")return null;let t=document.getElementById(K);if(!t)return null;try{return JSON.parse(t.textContent??"")}catch(e){return console.error("Modelence: failed to parse SSR state",e),null}}var v="__modelence_ssr_snapshot__";function I(t){globalThis[v]=t;}function je(){return globalThis[v]??null}function w(t){if(typeof window>"u"){I(t);return}let{loadingElement:e,routesElement:r,favicon:o,errorHandler:f,router:m,setupElement:k$1}=t;f&&E(f),window.addEventListener("unload",()=>{});let b=W(),y=H();y?.session&&(g(y.session),k());let g$2=document.getElementById("root"),O=window.location.pathname+window.location.search,h=m?m({children:r,location:O}):r,_=g$1()?h:jsx(n,{children:h}),M=jsx(R.StrictMode,{children:jsx(A,{loadingElement:e,setupElement:k$1,children:_})});if(b?C.hydrateRoot(g$2,M):C.createRoot(g$2).render(M),o){let T=document.querySelector("link[rel~='icon']");if(T)T.href=o;else {let s=document.createElement("link");s.rel="icon",s.href=o,document.head.appendChild(s);}}}export{c as a,q as b,je as c,w as d,u as e,A as f};//# sourceMappingURL=chunk-4I4BI7KD.js.map
|
|
2
|
-
//# sourceMappingURL=chunk-4I4BI7KD.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/module.ts","../src/system/client.ts","../src/websocket/clientChannel.ts","../src/client.ts","../src/client/renderApp.tsx"],"names":["createClientModule","moduleName","key","getConfig","name","rest","args","callMethod","getArgs","pageParam","systemConfig","ClientChannel","category","onMessage","getWebsocketClientProvider","id","AppProvider","React","SSR_STATE_SCRIPT_ID","hasSsrMarker","readSsrState","node","SNAPSHOT_KEY","setSnapshot","snapshot","_getSsrSnapshot","renderApp","options","loadingElement","routesElement","favicon","errorHandler","router","setupElement","setErrorHandler","isHydrating","ssrState","hydrateSession","startSessionHeartbeat","container","location","routedTree","appTree","hasConnectedQueryClient","jsx","ModelenceQueryProvider","tree","ReactDOM","link","newLink"],"mappings":"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","file":"chunk-4I4BI7KD.js","sourcesContent":["'use client';\n\nimport type { ObjectId } from 'mongodb';\nimport type { ConfigParams, ConfigType, ValueType } from '../config/types';\nimport { callMethod, type MethodArgs } from './method';\nimport type { AnyMethodShape } from '../methods/types';\n\n// Pulls the config store value without importing server-side code\nimport { getConfig as _getClientConfig } from '../config/client';\n\n// ── type helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Recursively maps ObjectId → string to match the sanitized runtime values\n * sent over the wire. Dates are preserved (revived via typeMap on the client).\n */\ntype Sanitized<T> = T extends ObjectId\n ? string\n : T extends Date\n ? Date\n : T extends (infer U)[]\n ? Sanitized<U>[]\n : T extends object\n ? { [K in keyof T]: Sanitized<T[K]> }\n : T;\n\ntype ExtractArgs<M> = M extends (args: infer A, ...rest: any[]) => any // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A\n : M extends { handler: (args: infer A, ...rest: any[]) => any } // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A\n : MethodArgs;\n\ntype ExtractResult<M> = M extends (...args: any[]) => Promise<infer R> // eslint-disable-line @typescript-eslint/no-explicit-any\n ? Sanitized<R>\n : M extends { handler: (...args: any[]) => Promise<infer R> } // eslint-disable-line @typescript-eslint/no-explicit-any\n ? Sanitized<R>\n : unknown;\n\ntype PublicKeyOf<TSchema extends Record<string, ConfigParams>> = {\n [K in keyof TSchema as TSchema[K] extends ConfigParams<ConfigType, true>\n ? string & K\n : never]: ValueType<TSchema[K]['type']>;\n};\n\ntype AnyModule = {\n name: string;\n configSchema: Record<string, ConfigParams>;\n queries: Record<string, AnyMethodShape>;\n mutations: Record<string, AnyMethodShape>;\n};\n\n// ── createClientModule ────────────────────────────────────────────────────────\n\n/**\n * Creates a typed client accessor for a module's public configs, queries, and mutations.\n *\n * Use `import type` to reference the module so no server code is bundled on the client.\n * Arg and return types for queries and mutations are inferred automatically from the\n * server-side handler signatures.\n *\n * @param moduleName - The module's name as passed to `new Module(name, ...)`.\n *\n * @example\n * ```ts\n * // src/client/payments.ts\n * import type paymentsModule from '../server/payments';\n * import { createClientModule } from 'modelence/client';\n *\n * export const payments = createClientModule<typeof paymentsModule>('payments');\n * ```\n *\n * ```ts\n * // src/components/Checkout.tsx\n * import { useQuery, useMutation } from '@tanstack/react-query';\n * import { payments } from '../client/payments';\n *\n * // Typed config — public keys only, private and secret keys excluded:\n * const currency = payments.getConfig('currency'); // string | undefined\n *\n * // Typed query — pass directly to useQuery:\n * const { data: products } = useQuery(payments.query('getProducts', { page: 1 }));\n *\n * // Typed mutation — pass directly to useMutation:\n * const { mutate: charge } = useMutation(payments.mutation('charge'));\n * charge({ amount: 100 }); // args typed from handler signature\n * ```\n */\nexport function createClientModule<TModule extends AnyModule>(moduleName: string) {\n return {\n getConfig<K extends keyof PublicKeyOf<TModule['configSchema']> & string>(\n key: K\n ): PublicKeyOf<TModule['configSchema']>[K] | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return _getClientConfig(`${moduleName}.${key}`) as any;\n },\n\n query<K extends keyof TModule['queries'] & string>(\n name: K,\n ...rest: {} extends ExtractArgs<TModule['queries'][K]>\n ? [args?: ExtractArgs<TModule['queries'][K]>]\n : [args: ExtractArgs<TModule['queries'][K]>]\n ) {\n const args = (rest[0] ?? {}) as ExtractArgs<TModule['queries'][K]>;\n return {\n queryKey: [moduleName, name, args] as const,\n queryFn: (): Promise<ExtractResult<TModule['queries'][K]>> =>\n callMethod<ExtractResult<TModule['queries'][K]>>(\n `${moduleName}.${name}`,\n args as MethodArgs\n ),\n };\n },\n\n mutation<K extends keyof TModule['mutations'] & string>(name: K) {\n return {\n mutationFn: (\n args: ExtractArgs<TModule['mutations'][K]>\n ): Promise<ExtractResult<TModule['mutations'][K]>> =>\n callMethod<ExtractResult<TModule['mutations'][K]>>(\n `${moduleName}.${name}`,\n args as MethodArgs\n ),\n };\n },\n\n /**\n * Returns options for `useInfiniteQuery`. The `getArgs` callback receives the\n * current `pageParam` and returns the args to pass to the query handler.\n * Spread the result into `useInfiniteQuery` alongside `getNextPageParam`.\n *\n * Annotate the `pageParam` type in the callback so TypeScript can infer the\n * page param type — no manual generic needed on `useInfiniteQuery`.\n */\n infiniteQuery<K extends keyof TModule['queries'] & string, TPageParam = unknown>(\n name: K,\n getArgs: (pageParam: TPageParam | undefined) => ExtractArgs<TModule['queries'][K]>\n ) {\n return {\n queryKey: [moduleName, name, 'infinite', getArgs(undefined)] as const,\n // Included so TanStack infers TPageParam from the callback type, not from a bare `undefined`.\n initialPageParam: undefined as TPageParam | undefined,\n queryFn: ({\n pageParam,\n }: {\n pageParam: TPageParam | undefined;\n }): Promise<ExtractResult<TModule['queries'][K]>> =>\n callMethod<ExtractResult<TModule['queries'][K]>>(\n `${moduleName}.${name}`,\n getArgs(pageParam) as MethodArgs\n ),\n };\n },\n };\n}\n","import type systemModule from './index';\nimport { createClientModule } from '../client/module';\n\nexport const systemConfig = createClientModule<typeof systemModule>('_system');\n","import { getWebsocketClientProvider } from './client';\n\nexport class ClientChannel<T = unknown> {\n public readonly category: string;\n private readonly onMessage: (data: T) => void;\n\n constructor(category: string, onMessage: (data: T) => void) {\n this.category = category;\n this.onMessage = onMessage;\n }\n\n init() {\n getWebsocketClientProvider()?.on({\n category: this.category,\n listener: this.onMessage,\n });\n }\n\n joinChannel(id: string) {\n getWebsocketClientProvider()?.joinChannel({\n category: this.category,\n id,\n });\n }\n\n leaveChannel(id: string) {\n getWebsocketClientProvider()?.leaveChannel({\n category: this.category,\n id,\n });\n }\n}\n","import React from 'react';\n\nimport { AppProvider as OriginalAppProvider } from './client/AppProvider';\n\nexport { configureClient, type ClientConfig } from './client/clientConfig';\nexport { getConfig } from './config/client';\nexport { createClientModule } from './client/module';\nexport type { ValueType } from './config/types';\nexport { systemConfig } from './system/client';\n\nexport const AppProvider =\n 'useClient' in React\n ? // @ts-ignore: React.useClient only exists in Next.js\n React.useClient(OriginalAppProvider)\n : OriginalAppProvider;\n\nexport { renderApp } from './client/renderApp';\nexport { ModelenceQueryProvider } from './client/queryProvider';\nexport {\n modelenceQuery,\n modelenceLiveQuery,\n modelenceMutation,\n createQueryKey,\n connectModelenceQueryClient,\n disconnectModelenceQueryClient,\n ModelenceQueryClient,\n type ModelenceQueryKey,\n} from './client/query';\nexport { callMethod, MethodError, type MethodArgs, type CallMethodOptions } from './client/method';\nexport { useSession } from './client/session';\nexport {\n signupWithPassword,\n loginWithPassword,\n verifyEmail,\n updateProfile,\n resendEmailVerification,\n logout,\n sendResetPasswordToken,\n resetPassword,\n sendMagicLink,\n loginWithMagicLink,\n loginWithOneTimeCode,\n linkOAuthProvider,\n unlinkOAuthProvider,\n type UserInfo,\n} from './auth/client';\nexport {\n getWebsocketClientProvider,\n setWebsocketClientProvider,\n startWebsockets,\n subscribeLiveQuery,\n} from './websocket/client';\nexport { ClientChannel } from './websocket/clientChannel';\nexport { getLocalStorageSession } from './client/localStorage';\n","import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { AppProvider } from '../client';\nimport { setErrorHandler, ErrorHandler } from './errorHandler';\nimport { hydrateSession, startSessionHeartbeat, type SessionInitPayload } from './session';\nimport { ModelenceQueryProvider } from './queryProvider';\nimport { hasConnectedQueryClient } from './query';\n\nconst SSR_STATE_SCRIPT_ID = '__MODELENCE_STATE__';\n\ntype SsrState = {\n session?: SessionInitPayload;\n};\n\nfunction hasSsrMarker(): boolean {\n if (typeof document === 'undefined') {\n return false;\n }\n return document.getElementById(SSR_STATE_SCRIPT_ID) !== null;\n}\n\nfunction readSsrState(): SsrState | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const node = document.getElementById(SSR_STATE_SCRIPT_ID);\n if (!node) {\n return null;\n }\n\n try {\n return JSON.parse(node.textContent ?? '') as SsrState;\n } catch (e) {\n // Caller must still hydrate (marker presence drives that, not parsed payload).\n console.error('Modelence: failed to parse SSR state', e);\n return null;\n }\n}\n\nexport type SsrRouter = (props: {\n children: React.ReactNode;\n location?: string;\n}) => React.ReactElement;\n\nexport interface RenderAppOptions {\n loadingElement: React.ReactNode;\n routesElement: React.ReactNode;\n favicon?: string;\n errorHandler?: ErrorHandler;\n router?: SsrRouter;\n /*\n Replaces the built-in setup screen shown when a development server has no\n backend yet (no Modelence Cloud connection, no local database). Pass\n `null` to disable the screen entirely.\n */\n setupElement?: React.ReactNode;\n}\n\n// Shared via globalThis: ssrLoadModule loads the user's entry in a separate\n// module graph from the framework runtime.\nconst SNAPSHOT_KEY = '__modelence_ssr_snapshot__';\n\ntype GlobalWithSnapshot = typeof globalThis & {\n [SNAPSHOT_KEY]?: RenderAppOptions | null;\n};\n\nfunction setSnapshot(snapshot: RenderAppOptions | null) {\n (globalThis as GlobalWithSnapshot)[SNAPSHOT_KEY] = snapshot;\n}\n\n/** @internal Used by the SSR runtime after evaluating the user's entry. */\nexport function _getSsrSnapshot(): RenderAppOptions | null {\n return (globalThis as GlobalWithSnapshot)[SNAPSHOT_KEY] ?? null;\n}\n\nexport function renderApp(options: RenderAppOptions) {\n if (typeof window === 'undefined') {\n setSnapshot(options);\n return;\n }\n\n const { loadingElement, routesElement, favicon, errorHandler, router, setupElement } = options;\n\n if (errorHandler) {\n setErrorHandler(errorHandler);\n }\n\n // Empty 'unload' handler prevents bfcache in most browsers.\n window.addEventListener('unload', () => {});\n\n // Hydrate session BEFORE building the tree so `isSessionInitialized()` is\n // true on the first render and matches the server output. Hydration mode\n // tracks marker presence (not parse success): a parse failure still leaves\n // server-rendered DOM that must be hydrated, not replaced.\n const isHydrating = hasSsrMarker();\n const ssrState = readSsrState();\n if (ssrState?.session) {\n hydrateSession(ssrState.session);\n // Fire-and-forget: the heartbeat loop runs in the background.\n void startSessionHeartbeat();\n }\n\n const container = document.getElementById('root')!;\n // Pass the same location the server used (req.originalUrl == path + search;\n // the hash is never sent to the server) so a location-driven router (e.g. a\n // static router) resolves the same route on hydration as it did during SSR,\n // avoiding hydration mismatches.\n const location = window.location.pathname + window.location.search;\n const routedTree = router ? router({ children: routesElement, location }) : routesElement;\n\n // If the app already connected its own QueryClient (the documented\n // bring-your-own-provider pattern connects before calling renderApp), don't\n // inject ours. A second provider would shadow the user's client: useQuery\n // would read the inner client while live-query updates write to the outer\n // one, so real-time queries would never update.\n const appTree = hasConnectedQueryClient() ? (\n routedTree\n ) : (\n <ModelenceQueryProvider>{routedTree}</ModelenceQueryProvider>\n );\n\n const tree = (\n <React.StrictMode>\n <AppProvider loadingElement={loadingElement} setupElement={setupElement}>\n {appTree}\n </AppProvider>\n </React.StrictMode>\n );\n\n if (isHydrating) {\n ReactDOM.hydrateRoot(container, tree);\n } else {\n ReactDOM.createRoot(container).render(tree);\n }\n\n if (favicon) {\n const link = document.querySelector(\"link[rel~='icon']\") as HTMLLinkElement;\n if (!link) {\n const newLink = document.createElement('link');\n newLink.rel = 'icon';\n newLink.href = favicon;\n document.head.appendChild(newLink);\n } else {\n link.href = favicon;\n }\n }\n}\n"]}
|
package/dist/chunk-KDOTVIEY.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import {a,b as b$1,n,j as j$1}from'./chunk-UW37F3GV.js';import {a as a$2,b as b$2}from'./chunk-5M6FUMUK.js';import {a as a$1}from'./chunk-DO5TZLF5.js';import {isDeepStrictEqual}from'util';import {MongoError,ObjectId,MongoServerError}from'mongodb';import {z}from'zod';import {createHash,randomBytes}from'crypto';var Z=class{constructor(e,{stores:t=[],queries:i={},mutations:r={},routes:a=[],cronJobs:c={},configSchema:d={},rateLimits:m=[],channels:g=[]}={}){this.name=e,this.stores=t,this.queries=i,this.mutations=r,this.routes=a,this.cronJobs=c,this.configSchema=d,this.rateLimits=m,this.channels=g;}getConfig(e){return a(`${this.name}.${e}`)}};function ie(){return process.env.NODE_ENV==="development"&&!process.env.MODELENCE_SERVICE_ENDPOINT&&!a("_system.mongodbUri")}function w(n){let e=n._def;if(e.typeName==="ZodString")return {type:"string"};if(e.typeName==="ZodNumber")return {type:"number"};if(e.typeName==="ZodBoolean")return {type:"boolean"};if(e.typeName==="ZodDate")return {type:"date"};if(e.typeName==="ZodArray")return {type:"array",items:w(e.type)};if(e.typeName==="ZodObject"){let i=e.shape(),r={};for(let[a,c]of Object.entries(i))r[a]=w(c);return {type:"object",items:r}}if(e.typeName==="ZodOptional")return {...w(e.innerType),optional:true};if(e.typeName==="ZodNullable")return {...w(e.innerType),optional:true};if(e.typeName==="ZodEnum")return {type:"enum",items:e.values};if(e.typeName==="ZodUnion")return {type:"union",items:e.options.map(w)};if(e.typeName==="ZodEffects"){let t=e;return t.description?{type:"custom",typeName:t.description}:w(t.schema)}return {type:"custom",typeName:e.typeName}}function N(n){let e={};for(let[t,i]of Object.entries(n))Array.isArray(i)?e[t]=i.map(r=>typeof r=="object"&&"_def"in r?w(r):N(r)):typeof i=="object"&&"_def"in i?e[t]=w(i):e[t]=N(i);return e}var j=n=>typeof n=="object"&&n!==null&&!Array.isArray(n),re=n=>j(n)&&"_def"in n,K=n=>n._def,oe=n=>{let e=K(n);if(e.typeName==="ZodOptional"||e.typeName==="ZodNullable"||e.typeName==="ZodDefault"||e.typeName==="ZodCatch"||e.typeName==="ZodReadonly")return e.innerType;if(e.typeName==="ZodEffects")return e.schema;if(e.typeName==="ZodBranded")return e.type;if(e.typeName==="ZodPipeline")return e.out},se=n=>{let e=K(n);if(e.typeName==="ZodDefault")return {hasDefault:true,value:e.defaultValue()};let t=oe(n);return t?se(t):{hasDefault:false}},Q=(n,e)=>{let t=K(n);if(t.typeName==="ZodObject"&&j(e))return $(t.shape(),e);if(t.typeName==="ZodArray"&&Array.isArray(e))return e.map(r=>Q(t.type,r));let i=oe(n);return i?Q(i,e):e},F=(n,e)=>re(n)?Q(n,e):Array.isArray(n)&&Array.isArray(e)?n.length===1?e.map(t=>F(n[0],t)):e.map((t,i)=>F(n[i],t)):j(n)&&j(e)?$(n,e):e,$=(n,e)=>{let t={...e};for(let[i,r]of Object.entries(n)){let a=t[i];if(a===void 0){if(re(r)){let c=se(r);c.hasDefault&&(t[i]=F(r,c.value));}continue}t[i]=F(r,a);}return t};var De="[modelence:index-error]";function ae(n){return n instanceof MongoServerError?n.code===11e3||n.message.includes("E11000"):false}function ce(n,e,t){let i={problem:"unique-index-violation",collection:n,index:{name:e.name??null,key:e.key,collation:e.collation??null,partialFilterExpression:e.partialFilterExpression??null},duplicateKey:t.keyValue??null,serverError:t.errmsg??t.message},r=e.collation?{collation:e.collation}:void 0,a=`db.getCollection(${JSON.stringify(n)}).aggregate(${JSON.stringify(we(e))}`+(r?`, ${JSON.stringify(r)}`:"")+")";return [`${De} Unique index '${e.name??JSON.stringify(e.key)}' on collection '${n}' could not be created because existing documents already violate it. Until this is resolved the constraint is NOT enforced, so new duplicates can still be written.`,`Details: ${JSON.stringify(i)}`,"Find the conflicting documents with:",` ${a}`,"Fix: merge, delete, or update the conflicting documents so each indexed value is unique, then restart the app \u2014 the index build is retried on startup."].join(`
|
|
2
|
-
`)}function we(n){let e=Object.keys(n.key),t=e.flatMap(r=>Ie(r).map(a=>({$unwind:{path:`$${a}`,preserveNullAndEmptyArrays:true}}))),i=Object.fromEntries(e.map(r=>[r.replace(/\./g,"_"),`$${r}`]));return [...n.partialFilterExpression?[{$match:n.partialFilterExpression}]:[],...t,{$group:{_id:i,ids:{$addToSet:"$_id"}}},{$match:{$expr:{$gt:[{$size:"$ids"},1]}}},{$limit:100}]}function Ie(n){let e=n.split(".");return e.map((t,i)=>e.slice(0,i+1).join("."))}var Oe=["background","bits","bucketSize","collation","default_language","expireAfterSeconds","hidden","language_override","max","min","partialFilterExpression","sparse","storageEngine","textIndexVersion","unique","weights","wildcardProjection","2dsphereIndexVersion"],J=n=>typeof n=="object"&&n!==null&&!Array.isArray(n),Ce=n=>n.startsWith("_modelence_"),H=n=>{let e={};for(let t of Oe){let i=n[t];i!==void 0&&(e[t]=i);}return e},ke=(n,e)=>{if(!J(n)||!J(e))return false;let t=Object.entries(n),i=Object.entries(e);return t.length!==i.length?false:t.every(([r,a],c)=>{let[d,m]=i[c]||[];return r===d&&isDeepStrictEqual(a,m)})},de=(n,e)=>ke(n.key,e.key)?isDeepStrictEqual(H(n),H(e)):false,V=n=>J(n)?Object.entries(n).map(([e,t])=>`${e}:${JSON.stringify(t)}`).join("|"):null,_e=async n=>{try{return await n.listIndexes().toArray()}catch(e){if(e instanceof MongoError&&e.code===26)return [];throw e}},Ae=n=>Object.entries(n).map(([e,t])=>`${e}_${t}`).join("_"),Me=n=>{if(n.name){let t=n.name.startsWith("_modelence_")?n.name:`_modelence_${n.name}`;return {...n,name:t}}let e=Ae(n.key);return {...n,name:`_modelence_${e}`}},f=class n{constructor(e,t){this._chainParent=null;this._chainChild=null;this.name=e,this.schema=t.schema,this.methods=t.methods,this.indexes=t.indexes.map(Me),this.searchIndexes=t.searchIndexes||[],this.indexCreationMode=t.indexCreationMode??"background";}getName(){return this.name}getIndexCreationMode(){return this.indexCreationMode}getSchema(){return this.schema}getSerializedSchema(){return N(this.schema)}getIndexes(){return this.indexes}getSearchIndexes(){return this.searchIndexes}getChainTail(){let e=this;for(;e._chainChild;)e=e._chainChild;return e}getChainRoot(){let e=this;for(;e._chainParent;)e=e._chainParent;return e}extend(e){let t=this.getChainTail();if(this.client||t.client)throw new Error(`Store.extend() must be called before startApp(). Store '${this.name}' has already been initialized and cannot be extended.`);let i={...t.schema,...e.schema||{}},r=[...t.indexes,...e.indexes||[]],a=[...t.searchIndexes,...e.searchIndexes||[]],c={...t.methods||{},...e.methods||{}},d=new n(this.name,{schema:i,methods:c,indexes:r,searchIndexes:a,indexCreationMode:e.indexCreationMode??t.indexCreationMode});return t._chainChild=d,d._chainParent=t,d}init(e){if(this.collection)throw new Error(`Collection ${this.name} is already initialized`);this.client=e,this.collection=this.client.db().collection(this.name);}async createIndexes(e="full"){let t=this.requireCollection(),i=e!=="create-only",r=e!=="drop-only",a=await _e(t),c=new Map,d=new Map,m=new Set,g=s=>{c.set(s.name,s);let l=V(s.key);if(!l)return;let u=d.get(l);u?u.add(s.name):d.set(l,new Set([s.name]));},D=s=>{let l=c.get(s);if(!l)return;c.delete(s);let u=V(l.key);if(!u)return;let T=d.get(u);T&&(T.delete(s),T.size===0&&d.delete(u));};for(let s of a)typeof s.name=="string"&&g({...s,name:s.name});let y=async s=>{if(!(s==="_id_"||m.has(s))){try{await t.dropIndex(s);}catch(l){if(!(l instanceof MongoError&&l.code===27))throw l}m.add(s),D(s);}};if(i){let s=new Set(this.indexes.map(u=>u.name).filter(u=>typeof u=="string")),l=[...c.values()].filter(u=>Ce(u.name)&&!s.has(u.name));for(let u of l)await y(u.name);}if(this.indexes.length>0)for(let s of this.indexes){if(!s.name)continue;let l=false,u=c.get(s.name);u&&!de(u,s)&&(i?await y(u.name):l=true);let T=V(s.key);if(T){let x=[...d.get(T)||[]];for(let O of x)O!==s.name&&(i?await y(O):l=true);}let v=c.get(s.name);if(!(!!v&&de(v,s))&&r&&!l){try{await t.createIndexes([s]);}catch(x){throw s.unique&&ae(x)&&console.error(ce(this.name,s,x)),x}g({name:s.name,key:s.key,...H(s)});}}if(r&&this.searchIndexes.length>0)for(let s of this.searchIndexes)try{await t.createSearchIndexes([s]);}catch(l){if(l instanceof MongoError&&l.code===68&&s.name)await t.dropSearchIndex(s.name),await t.createSearchIndexes([s]);else throw l}}wrapDocument(e){return this.methods?Object.create(null,Object.getOwnPropertyDescriptors({...e,...this.methods})):e}getSelector(e){return typeof e=="string"?{_id:new ObjectId(e)}:e instanceof ObjectId?{_id:e}:e}requireCollection(){if(!this.collection)throw new Error(`Collection ${this.name} is not provisioned`);return this.collection}requireClient(){if(!this.client)throw new Error("Database is not connected");return this.client}async findOne(e,t){let i=await this.requireCollection().findOne(e,t);return i?this.wrapDocument(i):null}async requireOne(e,t,i){let r=await this.findOne(e,t);if(!r)throw i?i():new Error(`Record not found in ${this.name}`);return r}find(e,t){let i=this.requireCollection().find(e,t?.projection?{projection:t.projection}:void 0);return t?.sort&&i.sort(t.sort),t?.limit&&i.limit(t.limit),t?.skip&&i.skip(t.skip),i}async findById(e){let t=typeof e=="string"?{_id:new ObjectId(e)}:{_id:e};return await this.findOne(t)}async requireById(e,t){let i=await this.findById(e);if(!i)throw t?t():new Error(`Record with id ${e} not found in ${this.name}`);return i}countDocuments(e){return this.requireCollection().countDocuments(e)}async fetch(e,t){return (await this.find(e,t).toArray()).map(this.wrapDocument.bind(this))}async insertOne(e,t){return await this.requireCollection().insertOne(e,t)}async create(e,t){let i=$(this.schema,{_id:new ObjectId,...e});return await this.requireCollection().insertOne(i,t),this.wrapDocument(i)}async insertMany(e,t){return await this.requireCollection().insertMany(e,t)}async updateOne(e,t,i){return await this.requireCollection().updateOne(this.getSelector(e),t,i)}async upsertOne(e,t,i){return await this.requireCollection().updateOne(this.getSelector(e),t,{upsert:true,...i})}async updateMany(e,t,i){return await this.requireCollection().updateMany(e,t,i)}async upsertMany(e,t,i){return await this.requireCollection().updateMany(e,t,{upsert:true,...i})}async deleteOne(e,t){return await this.requireCollection().deleteOne(this.getSelector(e),t)}async deleteMany(e,t){return await this.requireCollection().deleteMany(e,t)}async findOneAndUpdate(e,t,i){let r=await this.requireCollection().findOneAndUpdate(this.getSelector(e),t,i??{});return r?this.wrapDocument(r):null}async findOneAndUpsert(e,t,i){let r=await this.requireCollection().findOneAndUpdate(this.getSelector(e),t,{upsert:true,...i,returnDocument:"after",includeResultMetadata:true});return {doc:r.value?this.wrapDocument(r.value):null,isNew:!!r.lastErrorObject?.upserted}}async findOneAndDelete(e,t){let i=await this.requireCollection().findOneAndDelete(this.getSelector(e),t??{});return i?this.wrapDocument(i):null}async findOneAndReplace(e,t,i){let r=await this.requireCollection().findOneAndReplace(this.getSelector(e),t,i??{});return r?this.wrapDocument(r):null}async replaceOne(e,t,i){return await this.requireCollection().replaceOne(this.getSelector(e),t,i)}async distinct(e,t,i){let r=t??{};return i!==void 0?await this.requireCollection().distinct(e,r,i):await this.requireCollection().distinct(e,r)}watch(e,t){return this.requireCollection().watch(e,t)}aggregate(e,t){return this.requireCollection().aggregate(e,t)}bulkWrite(e){return this.requireCollection().bulkWrite(e)}getDatabase(){return this.requireClient().db()}rawCollection(){return this.requireCollection()}async renameFrom(e,t){let i=this.getDatabase();if(!this.collection||!i)throw new Error(`Store ${this.name} is not provisioned`);if((await i.listCollections({name:e}).toArray()).length===0)throw new Error(`Collection ${e} not found`);if((await i.listCollections({name:this.name}).toArray()).length>0)throw new Error(`Collection ${this.name} already exists`);await i.collection(e).rename(this.name,t);}async vectorSearch({field:e,embedding:t,numCandidates:i,limit:r,projection:a,indexName:c}){return this.aggregate([{$vectorSearch:{index:c||e+"VectorSearch",path:e,queryVector:t,numCandidates:i||100,limit:r||10}},{$project:{_id:1,score:{$meta:"vectorSearchScore"},...a}}])}static vectorIndex({field:e,dimensions:t,similarity:i="cosine",indexName:r}){return {type:"vectorSearch",name:r||e+"VectorSearch",definition:{fields:[{type:"vector",path:e,numDimensions:t,similarity:i}]}}}};var ve=z.string.bind(z),Ee=z.number.bind(z),Re=z.date.bind(z),Ze=z.boolean.bind(z),Ne=z.array.bind(z),je=z.object.bind(z),Fe=z.enum.bind(z),o={string:ve,number:Ee,date:Re,boolean:Ze,array:Ne,object:je,enum:Fe,embedding(){return z.array(z.number())},objectId(){return z.instanceof(ObjectId).describe("ObjectId")},userId(){return z.instanceof(ObjectId).describe("UserId")},ref(n){return z.instanceof(ObjectId).describe("Ref")},union:z.union.bind(z),infer(n){return {}}};function C(n){return createHash("sha256").update(n).digest("hex")}var G=new f("_modelenceLinkNonces",{schema:{nonce:o.string(),userId:o.string(),expiresAt:o.date()},indexes:[{key:{nonce:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]});async function nn(n){let e=randomBytes(32).toString("hex");return await G.insertOne({nonce:e,userId:n,expiresAt:new Date(Date.now()+a$1.minutes(10))}),e}async function rn(n){let e=await G.findOneAndDelete({nonce:n});return e?e.userId:null}var b=new f("_modelenceSessions",{schema:{authToken:o.string(),createdAt:o.date(),expiresAt:o.date(),userId:o.userId().nullable()},indexes:[{key:{authToken:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0},{key:{userId:1}}]});async function pe(n){if(n){let e=C(n),t=await b.findOne({authToken:e}),i=/^[0-9a-f]{64}$/i.test(n);if(!t&&!i&&(t=await b.findOne({authToken:n}),t&&await b.updateOne({_id:t._id},{$set:{authToken:e}})),t)return {authToken:n,expiresAt:new Date(t.expiresAt),userId:t.userId??null}}return await ze()}async function on(n,e){await b.updateOne({authToken:C(n)},{$set:{userId:e}});}async function sn(n){await b.updateOne({authToken:C(n)},{$set:{userId:null}});}async function an(n){await b.deleteMany({userId:n});}async function ze(n=null){let e=randomBytes(32).toString("base64url"),t=Date.now(),i=new Date(t+a$1.days(7));return await b.insertOne({authToken:C(e),createdAt:new Date(t),expiresAt:i,userId:n}),{authToken:e,expiresAt:i,userId:n}}async function Pe(n){let e=Date.now(),t=new Date(e+a$1.days(7));await b.updateOne({authToken:C(n.authToken)},{$set:{lastActiveDate:new Date(e),expiresAt:t}});}function qe(n,e){n.cookie("authToken",e,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/",maxAge:a$1.days(7)});}function cn(n){n.clearCookie("authToken",{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/"});}var dn=new Z("_system.session",{stores:[b,G],mutations:{init:async function(n,{session:e,user:t,res:i}){return i&&e?.userId&&qe(i,e.authToken),{session:e,user:t,configs:b$1(),...ie()?{setupRequired:true}:{}}},heartbeat:async function(n,{session:e}){e&&await Pe(e);}}});var he=new f("_modelenceUsers",{schema:{handle:o.string(),emails:o.array(o.object({address:o.string(),verified:o.boolean()})).optional(),status:o.enum(["active","disabled","deleted"]).optional(),firstName:o.string().optional(),lastName:o.string().optional(),avatarUrl:o.string().optional(),createdAt:o.date(),disabledAt:o.date().optional(),deletedAt:o.date().optional(),roles:o.array(o.string()).optional(),authMethods:o.object({password:o.object({hash:o.string()}).optional(),google:o.object({id:o.string()}).optional(),github:o.object({id:o.string()}).optional()})},indexes:[{key:{handle:1},unique:true,collation:{locale:"en",strength:2}},{key:{"emails.address":1,status:1}},{key:{"emails.address":1},unique:true,collation:{locale:"en",strength:2},partialFilterExpression:{"emails.address":{$exists:true}}},{key:{"authMethods.google.id":1},sparse:true,unique:true},{key:{"authMethods.github.id":1},sparse:true,unique:true}]}),hn=new f("_modelenceDisposableEmailDomains",{schema:{domain:o.string(),addedAt:o.date()},indexes:[{key:{domain:1},unique:true}]}),mn=new f("_modelenceEmailVerificationTokens",{schema:{userId:o.objectId(),email:o.string().optional(),token:o.string(),createdAt:o.date(),expiresAt:o.date()},indexes:[{key:{token:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]}),yn=new f("_modelenceResetPasswordTokens",{schema:{userId:o.objectId(),email:o.string().optional(),token:o.string(),createdAt:o.date(),expiresAt:o.date()},indexes:[{key:{token:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]}),fn=new f("_modelenceMagicLinkTokens",{schema:{email:o.string(),token:o.string(),code:o.string(),attempts:o.number(),createdAt:o.date(),expiresAt:o.date()},indexes:[{key:{token:1},unique:true},{key:{email:1}},{key:{expiresAt:1},expireAfterSeconds:0}]});var me=new Map,k={authenticated:null,unauthenticated:null};function Tn(n,e){k.authenticated=e.authenticated,k.unauthenticated=e.unauthenticated;for(let[t,i]of Object.entries(n))me.set(t,i);}function ye(){return k.unauthenticated?[k.unauthenticated]:[]}function fe(){return k.authenticated?[k.authenticated]:[]}function Y(n,e){let t=e.find(i=>!Le(n,i));if(t)throw new Error(`Access denied - missing permission: '${t}'`)}function Le(n,e){for(let t of n)if(me.get(t)?.permissions?.includes(e))return true;return false}async function ge(n){let e=await pe(n),t=e.userId?await he.findOne({_id:new ObjectId(e.userId),status:{$nin:["deleted","disabled"]}}):null,i=t?{id:t._id.toString(),handle:t.handle,roles:t.roles||[],hasRole:a=>(t.roles||[]).includes(a),requireRole:a=>{if(!(t.roles||[]).includes(a))throw new Error(`Access denied - role '${a}' required`)},firstName:t.firstName??void 0,lastName:t.lastName??void 0,avatarUrl:t.avatarUrl??void 0}:null,r=i?fe():ye();return {user:i,session:e,roles:r}}var A=class{constructor(e){this.fetch=e.fetch,this.watch=e.watch;}};function We(){return typeof window!="object"}function I(){if(!We())throw new Error("This function can only be called on the server")}function Cn(n){return n.replace(/<[^>]*>/g,"").replace(/\s+/g," ").trim()}var M=new Map;function Qe(n){let e=M.get(n.id);return e||(e=new Map,M.set(n.id,e)),e}async function Ke(n,e){let t=z.object({subscriptionId:z.string().min(1),method:z.string().min(1),args:z.record(z.unknown()).default({}),authToken:z.string().nullish(),clientInfo:z.object({screenWidth:z.number(),screenHeight:z.number(),windowWidth:z.number(),windowHeight:z.number(),pixelRatio:z.number(),orientation:z.string().nullable()}).optional()}).safeParse(e);if(!t.success){n.emit("liveQueryError",{subscriptionId:null,error:`Invalid payload: ${t.error.message}`});return}let{subscriptionId:i,method:r,args:a,authToken:c,clientInfo:d}=t.data,m=Qe(n),g=m.get(i);if(g)if(g.cleanup)try{g.cleanup();}catch(y){console.error("[LiveQuery] Error cleaning up existing subscription:",y);}else g.aborted=true;let D={cleanup:null};m.set(i,D);try{let{session:y,user:s,roles:l}=await ge(c??null),u={session:y,user:s,roles:l,clientInfo:d??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},connectionInfo:{ip:n.handshake.address,userAgent:n.handshake.headers["user-agent"]},req:null,res:null},T=await Te(r,a,u),v=async()=>{let S=a$2(await T.fetch());D.aborted||n.emit("liveQueryData",{subscriptionId:i,data:S,typeMap:b$2(S)});},E=!0,x=!1,O=()=>{D.aborted||!E||x||(E=!1,x=!0,v().catch(S=>{D.aborted||(console.error(`[LiveQuery] Error fetching data for ${r}:`,S),n.emit("liveQueryError",{subscriptionId:i,error:S instanceof Error?S.message:String(S)}));}).finally(()=>{x=!1,O();}));},L=T.watch({publish:()=>{E=!0,O();}});if(D.aborted){if(L)try{L();}catch(S){console.error("[LiveQuery] Error cleaning up after disconnect during setup:",S);}return}D.cleanup=L||null,O();}catch(y){m.delete(i),console.error(`[LiveQuery] Error in ${r}:`,y),n.emit("liveQueryError",{subscriptionId:i,error:y instanceof Error?y.message:String(y)});}}function Ve(n,e){let t=z.object({subscriptionId:z.string().min(1)}).safeParse(e);if(!t.success){console.warn(`[LiveQuery] Invalid unsubscribe payload: ${t.error.message}`);return}let{subscriptionId:i}=t.data,r=M.get(n.id);if(!r)return;let a=r.get(i);if(a){if(a.cleanup)try{a.cleanup();}catch(c){console.error("[LiveQuery] Error in cleanup:",c);}else a.aborted=true;r.delete(i);}}function Be(n){let e=M.get(n.id);if(e){for(let t of e.values())if(t.cleanup)try{t.cleanup();}catch(i){console.error("[LiveQuery] Error in cleanup on disconnect:",i);}else t.aborted=true;M.delete(n.id);}}var P={};function Pn(n,e){return I(),xe(n),q("query",n,e)}function qn(n,e){return I(),xe(n),q("mutation",n,e)}function Ln(n,e){return I(),Se(n),q("query",n,e)}function Un(n,e){return I(),Se(n),q("mutation",n,e)}function xe(n){if(n.toLowerCase().startsWith("_system."))throw new Error(`Method name cannot start with a reserved prefix: '_system.' (${n})`)}function Se(n){if(!n.toLowerCase().startsWith("_system."))throw new Error(`System method name must start with a prefix: '_system.' (${n})`)}function q(n,e,t){if(I(),P[e])throw new Error(`Method with name '${e}' is already defined.`);let i=typeof t=="function"?t:t.handler,r=typeof t=="function"?[]:t.permissions??[];P[e]={type:n,name:e,handler:i,permissions:r};}async function Wn(n$1,e,t){I();let i=P[n$1];if(!i)throw new Error(`Method with name '${n$1}' is not defined.`);let{type:r,handler:a}=i,c=n("method",`method:${n$1}`,{type:r,args:j$1(e)}),d;try{Y(t.roles,i.permissions),d=await a(e,t);}catch(m){throw c.end("error"),m}return c.end(),d}async function Te(n$1,e,t){I();let i=P[n$1];if(!i)throw new Error(`Method with name '${n$1}' is not defined.`);let{type:r,handler:a}=i;if(r!=="query")throw new Error("Live methods are only supported for queries");let c=n("method",`method:${n$1}:live`,{type:r,args:j$1(e)}),d;try{if(Y(t.roles,i.permissions),d=await a(e,t),!(d instanceof A))throw new Error(`Live query handler for '${n$1}' must return a LiveData object with fetch and watch functions. See https://docs.modelence.com/live-queries`)}catch(m){throw c.end("error"),m}return c.end(),d}
|
|
3
|
-
export{Pn as A,qn as B,Ln as C,Un as D,Wn as E,Ke as F,Ve as G,Be as H,Z as a,ie as b,f as c,o as d,C as e,nn as f,rn as g,b as h,pe as i,on as j,sn as k,an as l,ze as m,qe as n,cn as o,dn as p,he as q,hn as r,mn as s,yn as t,fn as u,Tn as v,ye as w,ge as x,A as y,Cn as z};//# sourceMappingURL=chunk-KDOTVIEY.js.map
|
|
4
|
-
//# sourceMappingURL=chunk-KDOTVIEY.js.map
|