modelence 0.4.12 → 0.4.13
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/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {b as b$1}from'./chunk-DN5SVAO2.js';import {a as a$1}from'./chunk-R7MPLJMA.js';import M,{useState,useEffect}from'react';import {create}from'zustand';import {z as z$1}from'zod';import {QueryClient,QueryClientProvider,useQuery,useMutation}from'@tanstack/react-query';import {jsx}from'react/jsx-runtime';import J from'react-dom/client';function g(){let e=localStorage.getItem("modelence.session");try{return e?JSON.parse(e):null}catch(r){return console.error("Error parsing session from localStorage",r),null}}function m(e){localStorage.setItem("modelence.session",JSON.stringify(e));}var h=(e,r)=>{throw new Error(`Error calling method '${r}': ${e.toString()}`)};function w(e){h=e;}function y(e,r){return h(e,r)}async function n(e,r={}){try{return await b(`/api/_internal/method/${e}`,r)}catch(t){throw y(t,e),t}}async function b(e,r){let t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({args:r,authToken:g()?.authToken,clientInfo:{screenWidth:window.screen.width,screenHeight:window.screen.height,windowWidth:window.innerWidth,windowHeight:window.innerHeight,pixelRatio:window.devicePixelRatio,orientation:window.screen.orientation?.type}})});if(!t.ok){let s=await t.text();throw new Error(s)}let o=await t.text(),i=o?JSON.parse(o):void 0;if(!i)throw new Error("Invalid response from server");return b$1(i.data,i.typeMap)}function
|
|
1
|
+
import {b as b$1}from'./chunk-DN5SVAO2.js';import {a as a$1}from'./chunk-R7MPLJMA.js';import M,{useState,useEffect}from'react';import {create}from'zustand';import {z as z$1}from'zod';import {QueryClient,QueryClientProvider,useQuery,useMutation}from'@tanstack/react-query';import {jsx}from'react/jsx-runtime';import J from'react-dom/client';function g(){let e=localStorage.getItem("modelence.session");try{return e?JSON.parse(e):null}catch(r){return console.error("Error parsing session from localStorage",r),null}}function m(e){localStorage.setItem("modelence.session",JSON.stringify(e));}var h=(e,r)=>{throw new Error(`Error calling method '${r}': ${e.toString()}`)};function w(e){h=e;}function y(e,r){return h(e,r)}async function n(e,r={}){try{return await b(`/api/_internal/method/${e}`,r)}catch(t){throw y(t,e),t}}async function b(e,r){let t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({args:r,authToken:g()?.authToken,clientInfo:{screenWidth:window.screen.width,screenHeight:window.screen.height,windowWidth:window.innerWidth,windowHeight:window.innerHeight,pixelRatio:window.devicePixelRatio,orientation:window.screen.orientation?.type}})});if(!t.ok){let s=await t.text();throw new Error(s)}let o=await t.text(),i=o?JSON.parse(o):void 0;if(!i)throw new Error("Invalid response from server");return b$1(i.data,i.typeMap)}function O(e,r={},t){let o=useQuery({queryKey:[e,r],queryFn:()=>n(e,r),enabled:t?.enabled??true,placeholderData:t?.placeholderData});return {data:o.data??null,error:o.error,isFetching:o.isFetching,refetch:()=>o.refetch()}}function k(e,r={}){let t=useMutation({mutationFn:(o={})=>n(e,{...r,...o})});return {data:t.data??null,error:t.error,isFetching:t.isPending,isPending:t.isPending,mutate:t.mutate,mutateAsync:t.mutateAsync}}var a={};function L(e){if(!(e in a))throw new Error(`Unknown config: ${e}`);return a[e]?.value}function S(e){a=e;}var u=create(e=>({user:null,setUser:r=>e({user:r})})),E=false,I=a$1.seconds(30);async function T(){if(E)return;E=true;let{configs:e,session:r,user:t}=await n("_system.session.init");S(e),m(r);let o=t?Object.freeze(z$1.object({id:z$1.string(),handle:z$1.string()}).parse(t)):null;u.getState().setUser(o),await x();}async function x(){await n("_system.session.heartbeat"),setTimeout(x,I);}function c(e){u.getState().setUser(e);}function N(){return {user:u(r=>r.user)}}var P=false,D=new QueryClient({defaultOptions:{queries:{refetchOnWindowFocus:false}}});function d({children:e,loadingElement:r}){let[t,o]=useState(true);return useEffect(()=>{async function i(){P||(P=true,await T(),o(false));}i();},[]),t?r??jsx("div",{children:"Loading..."}):jsx(QueryClientProvider,{client:D,children:e})}function j({loadingElement:e,routesElement:r,favicon:t,errorHandler:o}){if(o&&w(o),window.addEventListener("unload",()=>{}),J.createRoot(document.getElementById("root")).render(jsx(M.StrictMode,{children:jsx(v,{loadingElement:e,children:r})})),t){let i=document.querySelector("link[rel~='icon']");if(i)i.href=t;else {let s=document.createElement("link");s.rel="icon",s.href=t,document.head.appendChild(s);}}}async function z({email:e,password:r}){await n("_system.user.signupWithPassword",{email:e,password:r}),await R({email:e,password:r});}async function R({email:e,password:r}){let{user:t}=await n("_system.user.loginWithPassword",{email:e,password:r});return c(t),t}async function $(){await n("_system.user.logout"),c(null);}var v="useClient"in M?M.useClient(d):d;export{v as AppProvider,n as callMethod,L as getConfig,R as loginWithPassword,$ as logout,j as renderApp,z as signupWithPassword,k as useMutation,O as useQuery,N as useSession};//# sourceMappingURL=client.js.map
|
|
2
2
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/localStorage.ts","../src/client/errorHandler.ts","../src/client/method.ts","../src/config/client.ts","../src/client/session.ts","../src/client/AppProvider.tsx","../src/client/renderApp.tsx","../src/auth/client/index.ts","../src/client.ts"],"names":["getLocalStorageSession","sessionJson","e","setLocalStorageSession","session","errorHandler","error","methodName","setErrorHandler","handler","handleError","callMethod","args","call","endpoint","response","text","result","reviveResponseTypes","useQuery","options","query","useTanQuery","useMutation","mutation","useTanMutation","newArgs","config","getConfig","key","_setConfig","configs","useSessionStore","create","set","user","isInitialized","SESSION_HEARTBEAT_INTERVAL","time","initSession","parsedUser","z","loopSessionHeartbeat","setCurrentUser","useSession","state","queryClient","QueryClient","AppProvider","children","loadingElement","isLoading","setIsLoading","useState","useEffect","initConfig","jsx","QueryClientProvider","renderApp","routesElement","favicon","ReactDOM","React","link","newLink","signupWithPassword","email","password","loginWithPassword","logout"],"mappings":"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","file":"client.js","sourcesContent":["export function getLocalStorageSession() {\n const sessionJson = localStorage.getItem('modelence.session');\n try {\n return sessionJson ? JSON.parse(sessionJson) : null;\n } catch (e) {\n console.error('Error parsing session from localStorage', e);\n return null;\n }\n}\n\nexport function setLocalStorageSession(session: object) {\n localStorage.setItem('modelence.session', JSON.stringify(session));\n}\n","export type ErrorHandler = (error: Error, methodName: string) => void;\n\nlet errorHandler: ErrorHandler = (error, methodName) => {\n throw new Error(`Error calling method '${methodName}': ${error.toString()}`);\n};\n\nexport function setErrorHandler(handler: ErrorHandler) {\n errorHandler = handler;\n}\n\nexport function handleError(error: Error, methodName: string) {\n return errorHandler(error, methodName);\n}\n","/**\n * @group React Hooks\n * Client-side React hooks for data fetching and mutations\n */\n\n/*\n The \"use client\" directive is specifically for the Next.js layout component, which is rendered on the server by default.\n Because of this, we are explicitly marking it as a client component, so we can render this component on the client\n and properly initialize config on the client side.\n \n While this is specific to Next.js, it is simply ignored outside of Next.js and should not cause errors.\n*/\n\"use client\";\n\nimport { useQuery as useTanQuery, useMutation as useTanMutation } from '@tanstack/react-query';\nimport { getLocalStorageSession } from './localStorage';\nimport { handleError } from './errorHandler';\nimport { reviveResponseTypes } from '../methods/serialize';\n\ntype Args = Record<string, unknown>;\n\ntype MethodResult<T> = {\n isFetching: boolean;\n error: Error | null;\n data: T | null;\n};\n\ntype PlaceholderData<T> = T | ((prev: T | null) => T);\n\ntype QueryOptions<T> = {\n enabled?: boolean;\n placeholderData?: PlaceholderData<T>;\n};\n\nexport async function callMethod<T = unknown>(methodName: string, args: Args = {}): Promise<T> {\n try {\n return await call<T>(`/api/_internal/method/${methodName}`, args);\n } catch (error) {\n handleError(error as Error, methodName);\n throw error;\n }\n}\n\nasync function call<T = unknown>(endpoint: string, args: Args): Promise<T> {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n args,\n authToken: getLocalStorageSession()?.authToken,\n clientInfo: {\n screenWidth: window.screen.width,\n screenHeight: window.screen.height,\n windowWidth: window.innerWidth,\n windowHeight: window.innerHeight,\n pixelRatio: window.devicePixelRatio,\n orientation: window.screen.orientation?.type\n }\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(error);\n }\n\n const text = await response.text();\n const result = text ? JSON.parse(text) : undefined;\n if (!result) {\n throw new Error('Invalid response from server');\n }\n\n return reviveResponseTypes(result.data, result.typeMap);\n}\n\n/**\n * React hook for executing a query method.\n * \n * This hook automatically executes the query on mount and provides a refetch capability.\n * Similar to React Query's useQuery hook.\n * \n * @typeParam T - The expected return type of the query\n * @param methodName - The name of the method to query\n * @param args - Optional arguments to pass to the method\n * @param options - Optional options object\n * @param options.enabled - Boolean indicating if the query should be enabled\n * @returns {Object} An object containing the query state and a refetch function:\n * - `data` - The data returned by the query, or null if not yet loaded\n * - `isFetching` - Boolean indicating if the query is in progress\n * - `error` - Any error that occurred during the query, or null\n * - `refetch` - Function to manually trigger a refetch with optional new arguments\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * // This is assuming you have a Module named \"todo\" with a query named \"getItem\"\n * const { data, isFetching, error } = useQuery<Todo>('todo.getItem', { id: '123' });\n * if (isFetching) {\n * return <div>Loading...</div>;\n * }\n * if (error) {\n * return <div>Error: {error.message}</div>;\n * }\n * return <div>{data?.name}</div>;\n * }\n * ```\n */\nexport function useQuery<T = unknown>(\n methodName: string, \n args: Args = {}, \n options?: QueryOptions<T>\n): MethodResult<T> & {\n /** Function to manually trigger a refetch of the query with optional new arguments */\n refetch: (args?: Args) => void\n} {\n type QueryKey = [string, Args];\n \n const query = useTanQuery<T, Error, T, QueryKey>({\n queryKey: [methodName, args],\n queryFn: () => callMethod<T>(methodName, args),\n enabled: options?.enabled ?? true,\n placeholderData: options?.placeholderData as any\n });\n\n return {\n data: query.data ?? null,\n error: query.error as Error | null,\n isFetching: query.isFetching,\n refetch: () => query.refetch(),\n };\n}\n\n/**\n * React hook for executing a mutation method.\n * \n * This hook provides functions to trigger the mutation manually and handles loading/error states.\n * Similar to React Query's useMutation hook.\n * \n * @typeParam T - The expected return type of the mutation\n * @param methodName - The name of the method to mutate\n * @param args - Optional default arguments to pass to the method\n * @returns {Object} An object containing the mutation state and trigger functions:\n * - `data` - The data returned by the last successful mutation, or null\n * - `isFetching` - Boolean indicating if the mutation is in progress\n * - `error` - Any error that occurred during the last mutation, or null\n * - `mutate` - Function to trigger the mutation with optional arguments\n * - `mutateAsync` - Promise-returning version of mutate, useful for awaiting the result\n * \n * @example\n * ```tsx\n * const { mutate: updateTodo, isFetching, error } = useMutation<User>('todos.update');\n * \n * // Later in your code:\n * updateTodo({ id: '123', name: 'New Name' });\n * ```\n */\nexport function useMutation<T = unknown>(methodName: string, args: Args = {}) {\n const mutation = useTanMutation({\n mutationFn: (newArgs: Args = {}) => callMethod<T>(methodName, { ...args, ...newArgs }),\n });\n\n return {\n data: mutation.data ?? null,\n error: mutation.error as Error | null,\n isFetching: mutation.isPending, // Legacy\n isPending: mutation.isPending,\n mutate: mutation.mutate,\n mutateAsync: mutation.mutateAsync,\n };\n}\n","import { ConfigKey, AppConfig, Configs } from './types';\n\nlet config: Record<ConfigKey, AppConfig> = {};\n\nexport function getConfig(key: ConfigKey) {\n if (!(key in config)) {\n throw new Error(`Unknown config: ${key}`);\n }\n\n return config[key]?.value;\n}\n\nexport function _setConfig(configs: Configs) {\n config = configs;\n}\n","import { create } from 'zustand';\nimport { z } from 'zod';\nimport { callMethod } from './method';\nimport { _setConfig } from '../config/client';\nimport { setLocalStorageSession } from './localStorage';\nimport { time } from '../time';\nimport { Configs } from '../config/types';\n\ntype User = {\n id: string;\n handle: string;\n};\n\ntype SessionStore = {\n user: User | null;\n setUser: (user: User | null) => void;\n};\n\nexport const useSessionStore = create<SessionStore>((set) => ({\n user: null,\n setUser: (user) => set({ user }),\n}));\n\nlet isInitialized = false;\nconst SESSION_HEARTBEAT_INTERVAL = time.seconds(30);\n\nexport async function initSession() {\n if (isInitialized) {\n return;\n }\n\n isInitialized = true;\n\n const { configs, session, user } = await callMethod<{ configs: Configs, session: object, user: object }>('_system.session.init');\n _setConfig(configs);\n setLocalStorageSession(session);\n \n const parsedUser = user ? Object.freeze(z.object({\n id: z.string(),\n handle: z.string(),\n }).parse(user)) : null;\n\n useSessionStore.getState().setUser(parsedUser);\n\n await loopSessionHeartbeat();\n}\n\nasync function loopSessionHeartbeat() {\n await callMethod('_system.session.heartbeat');\n setTimeout(loopSessionHeartbeat, SESSION_HEARTBEAT_INTERVAL);\n}\n\nexport function setCurrentUser(user: User | null) {\n useSessionStore.getState().setUser(user);\n}\n\nexport function useSession() {\n const user = useSessionStore(state => state.user);\n return { user };\n}\n","/*\n The \"use client\" directive is specifically for the Next.js layout component, which is rendered on the server by default.\n Because of this, we are explicitly marking it as a client component, so we can render this component on the client\n and properly initialize config on the client side.\n \n While this is specific to Next.js, it is simply ignored outside of Next.js and should not cause errors.\n*/\n\"use client\";\n\nimport React, { useState, useEffect, ReactNode } from 'react';\nimport { initSession } from './session';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\ninterface AppProviderProps {\n children: ReactNode;\n loadingElement?: ReactNode;\n}\n\nlet isInitialized = false;\n\nexport const queryClient = new QueryClient();\n\nexport function AppProvider({ children, loadingElement }: AppProviderProps) {\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n async function initConfig() {\n if (isInitialized) {\n return;\n }\n\n isInitialized = true;\n\n await initSession();\n setIsLoading(false);\n }\n\n initConfig();\n }, []);\n\n if (isLoading) {\n return loadingElement ?? <div>Loading...</div>;\n }\n\n return (\n <QueryClientProvider client={queryClient}>\n {children}\n </QueryClientProvider>\n );\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { AppProvider } from '../client';\nimport { setErrorHandler, ErrorHandler } from './errorHandler';\n\nexport function renderApp({ loadingElement, routesElement, favicon, errorHandler }: {\n loadingElement: React.ReactNode,\n routesElement: React.ReactNode,\n favicon?: string,\n errorHandler?: ErrorHandler\n}) {\n if (errorHandler) {\n setErrorHandler(errorHandler);\n }\n\n window.addEventListener('unload', () => {\n // The presence of any 'unload' event handler, even empty,\n // prevents bfcache in most browsers\n });\n\n ReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <AppProvider loadingElement={loadingElement}>\n {routesElement}\n </AppProvider>\n </React.StrictMode>\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","import { setCurrentUser } from '../../client/session';\nimport { callMethod } from '../../client/method';\n\ntype User = {\n id: string;\n handle: string;\n};\n\nexport async function signupWithPassword({ email, password }: { email: string, password: string }) {\n await callMethod('_system.user.signupWithPassword', { email, password });\n\n // TODO: handle auto-login from the signup method itself to avoid a second method call\n await loginWithPassword({ email, password });\n}\n\nexport async function loginWithPassword({ email, password }: { email: string, password: string }) {\n const { user } = await callMethod<{ user: User }>('_system.user.loginWithPassword', { email, password });\n setCurrentUser(user);\n return user;\n}\n\nexport async function logout() {\n await callMethod('_system.user.logout');\n setCurrentUser(null);\n}","import React from 'react';\n\nimport { AppProvider as OriginalAppProvider } from './client/AppProvider';\n\nexport { getConfig } from './config/client';\n\nexport const AppProvider = '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 { useQuery, useMutation, callMethod } from './client/method';\nexport { useSession } from './client/session';\nexport { signupWithPassword, loginWithPassword, logout } from './auth/client';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/localStorage.ts","../src/client/errorHandler.ts","../src/client/method.ts","../src/config/client.ts","../src/client/session.ts","../src/client/AppProvider.tsx","../src/client/renderApp.tsx","../src/auth/client/index.ts","../src/client.ts"],"names":["getLocalStorageSession","sessionJson","e","setLocalStorageSession","session","errorHandler","error","methodName","setErrorHandler","handler","handleError","callMethod","args","call","endpoint","response","text","result","reviveResponseTypes","useQuery","options","query","useTanQuery","useMutation","mutation","useTanMutation","newArgs","config","getConfig","key","_setConfig","configs","useSessionStore","create","set","user","isInitialized","SESSION_HEARTBEAT_INTERVAL","time","initSession","parsedUser","z","loopSessionHeartbeat","setCurrentUser","useSession","state","queryClient","QueryClient","AppProvider","children","loadingElement","isLoading","setIsLoading","useState","useEffect","initConfig","jsx","QueryClientProvider","renderApp","routesElement","favicon","ReactDOM","React","link","newLink","signupWithPassword","email","password","loginWithPassword","logout"],"mappings":"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","file":"client.js","sourcesContent":["export function getLocalStorageSession() {\n const sessionJson = localStorage.getItem('modelence.session');\n try {\n return sessionJson ? JSON.parse(sessionJson) : null;\n } catch (e) {\n console.error('Error parsing session from localStorage', e);\n return null;\n }\n}\n\nexport function setLocalStorageSession(session: object) {\n localStorage.setItem('modelence.session', JSON.stringify(session));\n}\n","export type ErrorHandler = (error: Error, methodName: string) => void;\n\nlet errorHandler: ErrorHandler = (error, methodName) => {\n throw new Error(`Error calling method '${methodName}': ${error.toString()}`);\n};\n\nexport function setErrorHandler(handler: ErrorHandler) {\n errorHandler = handler;\n}\n\nexport function handleError(error: Error, methodName: string) {\n return errorHandler(error, methodName);\n}\n","/**\n * @group React Hooks\n * Client-side React hooks for data fetching and mutations\n */\n\n/*\n The \"use client\" directive is specifically for the Next.js layout component, which is rendered on the server by default.\n Because of this, we are explicitly marking it as a client component, so we can render this component on the client\n and properly initialize config on the client side.\n \n While this is specific to Next.js, it is simply ignored outside of Next.js and should not cause errors.\n*/\n\"use client\";\n\nimport { useQuery as useTanQuery, useMutation as useTanMutation } from '@tanstack/react-query';\nimport { getLocalStorageSession } from './localStorage';\nimport { handleError } from './errorHandler';\nimport { reviveResponseTypes } from '../methods/serialize';\n\ntype Args = Record<string, unknown>;\n\ntype MethodResult<T> = {\n isFetching: boolean;\n error: Error | null;\n data: T | null;\n};\n\ntype PlaceholderData<T> = T | ((prev: T | null) => T);\n\ntype QueryOptions<T> = {\n enabled?: boolean;\n placeholderData?: PlaceholderData<T>;\n};\n\nexport async function callMethod<T = unknown>(methodName: string, args: Args = {}): Promise<T> {\n try {\n return await call<T>(`/api/_internal/method/${methodName}`, args);\n } catch (error) {\n handleError(error as Error, methodName);\n throw error;\n }\n}\n\nasync function call<T = unknown>(endpoint: string, args: Args): Promise<T> {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n args,\n authToken: getLocalStorageSession()?.authToken,\n clientInfo: {\n screenWidth: window.screen.width,\n screenHeight: window.screen.height,\n windowWidth: window.innerWidth,\n windowHeight: window.innerHeight,\n pixelRatio: window.devicePixelRatio,\n orientation: window.screen.orientation?.type\n }\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(error);\n }\n\n const text = await response.text();\n const result = text ? JSON.parse(text) : undefined;\n if (!result) {\n throw new Error('Invalid response from server');\n }\n\n return reviveResponseTypes(result.data, result.typeMap);\n}\n\n/**\n * React hook for executing a query method.\n * \n * This hook automatically executes the query on mount and provides a refetch capability.\n * Similar to React Query's useQuery hook.\n * \n * @typeParam T - The expected return type of the query\n * @param methodName - The name of the method to query\n * @param args - Optional arguments to pass to the method\n * @param options - Optional options object\n * @param options.enabled - Boolean indicating if the query should be enabled\n * @returns {Object} An object containing the query state and a refetch function:\n * - `data` - The data returned by the query, or null if not yet loaded\n * - `isFetching` - Boolean indicating if the query is in progress\n * - `error` - Any error that occurred during the query, or null\n * - `refetch` - Function to manually trigger a refetch with optional new arguments\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * // This is assuming you have a Module named \"todo\" with a query named \"getItem\"\n * const { data, isFetching, error } = useQuery<Todo>('todo.getItem', { id: '123' });\n * if (isFetching) {\n * return <div>Loading...</div>;\n * }\n * if (error) {\n * return <div>Error: {error.message}</div>;\n * }\n * return <div>{data?.name}</div>;\n * }\n * ```\n */\nexport function useQuery<T = unknown>(\n methodName: string, \n args: Args = {}, \n options?: QueryOptions<T>\n): MethodResult<T> & {\n /** Function to manually trigger a refetch of the query with optional new arguments */\n refetch: (args?: Args) => void\n} {\n type QueryKey = [string, Args];\n \n const query = useTanQuery<T, Error, T, QueryKey>({\n queryKey: [methodName, args],\n queryFn: () => callMethod<T>(methodName, args),\n enabled: options?.enabled ?? true,\n placeholderData: options?.placeholderData as any\n });\n\n return {\n data: query.data ?? null,\n error: query.error as Error | null,\n isFetching: query.isFetching,\n refetch: () => query.refetch(),\n };\n}\n\n/**\n * React hook for executing a mutation method.\n * \n * This hook provides functions to trigger the mutation manually and handles loading/error states.\n * Similar to React Query's useMutation hook.\n * \n * @typeParam T - The expected return type of the mutation\n * @param methodName - The name of the method to mutate\n * @param args - Optional default arguments to pass to the method\n * @returns {Object} An object containing the mutation state and trigger functions:\n * - `data` - The data returned by the last successful mutation, or null\n * - `isFetching` - Boolean indicating if the mutation is in progress\n * - `error` - Any error that occurred during the last mutation, or null\n * - `mutate` - Function to trigger the mutation with optional arguments\n * - `mutateAsync` - Promise-returning version of mutate, useful for awaiting the result\n * \n * @example\n * ```tsx\n * const { mutate: updateTodo, isFetching, error } = useMutation<User>('todos.update');\n * \n * // Later in your code:\n * updateTodo({ id: '123', name: 'New Name' });\n * ```\n */\nexport function useMutation<T = unknown>(methodName: string, args: Args = {}) {\n const mutation = useTanMutation({\n mutationFn: (newArgs: Args = {}) => callMethod<T>(methodName, { ...args, ...newArgs }),\n });\n\n return {\n data: mutation.data ?? null,\n error: mutation.error as Error | null,\n isFetching: mutation.isPending, // Legacy\n isPending: mutation.isPending,\n mutate: mutation.mutate,\n mutateAsync: mutation.mutateAsync,\n };\n}\n","import { ConfigKey, AppConfig, Configs } from './types';\n\nlet config: Record<ConfigKey, AppConfig> = {};\n\nexport function getConfig(key: ConfigKey) {\n if (!(key in config)) {\n throw new Error(`Unknown config: ${key}`);\n }\n\n return config[key]?.value;\n}\n\nexport function _setConfig(configs: Configs) {\n config = configs;\n}\n","import { create } from 'zustand';\nimport { z } from 'zod';\nimport { callMethod } from './method';\nimport { _setConfig } from '../config/client';\nimport { setLocalStorageSession } from './localStorage';\nimport { time } from '../time';\nimport { Configs } from '../config/types';\n\ntype User = {\n id: string;\n handle: string;\n};\n\ntype SessionStore = {\n user: User | null;\n setUser: (user: User | null) => void;\n};\n\nexport const useSessionStore = create<SessionStore>((set) => ({\n user: null,\n setUser: (user) => set({ user }),\n}));\n\nlet isInitialized = false;\nconst SESSION_HEARTBEAT_INTERVAL = time.seconds(30);\n\nexport async function initSession() {\n if (isInitialized) {\n return;\n }\n\n isInitialized = true;\n\n const { configs, session, user } = await callMethod<{ configs: Configs, session: object, user: object }>('_system.session.init');\n _setConfig(configs);\n setLocalStorageSession(session);\n \n const parsedUser = user ? Object.freeze(z.object({\n id: z.string(),\n handle: z.string(),\n }).parse(user)) : null;\n\n useSessionStore.getState().setUser(parsedUser);\n\n await loopSessionHeartbeat();\n}\n\nasync function loopSessionHeartbeat() {\n await callMethod('_system.session.heartbeat');\n setTimeout(loopSessionHeartbeat, SESSION_HEARTBEAT_INTERVAL);\n}\n\nexport function setCurrentUser(user: User | null) {\n useSessionStore.getState().setUser(user);\n}\n\nexport function useSession() {\n const user = useSessionStore(state => state.user);\n return { user };\n}\n","/*\n The \"use client\" directive is specifically for the Next.js layout component, which is rendered on the server by default.\n Because of this, we are explicitly marking it as a client component, so we can render this component on the client\n and properly initialize config on the client side.\n \n While this is specific to Next.js, it is simply ignored outside of Next.js and should not cause errors.\n*/\n\"use client\";\n\nimport React, { useState, useEffect, ReactNode } from 'react';\nimport { initSession } from './session';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\ninterface AppProviderProps {\n children: ReactNode;\n loadingElement?: ReactNode;\n}\n\nlet isInitialized = false;\n\nexport const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n },\n },\n});\n\nexport function AppProvider({ children, loadingElement }: AppProviderProps) {\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n async function initConfig() {\n if (isInitialized) {\n return;\n }\n\n isInitialized = true;\n\n await initSession();\n setIsLoading(false);\n }\n\n initConfig();\n }, []);\n\n if (isLoading) {\n return loadingElement ?? <div>Loading...</div>;\n }\n\n return (\n <QueryClientProvider client={queryClient}>\n {children}\n </QueryClientProvider>\n );\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { AppProvider } from '../client';\nimport { setErrorHandler, ErrorHandler } from './errorHandler';\n\nexport function renderApp({ loadingElement, routesElement, favicon, errorHandler }: {\n loadingElement: React.ReactNode,\n routesElement: React.ReactNode,\n favicon?: string,\n errorHandler?: ErrorHandler\n}) {\n if (errorHandler) {\n setErrorHandler(errorHandler);\n }\n\n window.addEventListener('unload', () => {\n // The presence of any 'unload' event handler, even empty,\n // prevents bfcache in most browsers\n });\n\n ReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <AppProvider loadingElement={loadingElement}>\n {routesElement}\n </AppProvider>\n </React.StrictMode>\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","import { setCurrentUser } from '../../client/session';\nimport { callMethod } from '../../client/method';\n\ntype User = {\n id: string;\n handle: string;\n};\n\nexport async function signupWithPassword({ email, password }: { email: string, password: string }) {\n await callMethod('_system.user.signupWithPassword', { email, password });\n\n // TODO: handle auto-login from the signup method itself to avoid a second method call\n await loginWithPassword({ email, password });\n}\n\nexport async function loginWithPassword({ email, password }: { email: string, password: string }) {\n const { user } = await callMethod<{ user: User }>('_system.user.loginWithPassword', { email, password });\n setCurrentUser(user);\n return user;\n}\n\nexport async function logout() {\n await callMethod('_system.user.logout');\n setCurrentUser(null);\n}","import React from 'react';\n\nimport { AppProvider as OriginalAppProvider } from './client/AppProvider';\n\nexport { getConfig } from './config/client';\n\nexport const AppProvider = '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 { useQuery, useMutation, callMethod } from './client/method';\nexport { useSession } from './client/session';\nexport { signupWithPassword, loginWithPassword, logout } from './auth/client';\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var s="module",i="modelence",n="0.4.
|
|
2
|
-
export{u as author,l as bin,y as bugs,x as default,v as dependencies,o as description,b as devDependencies,c as exports,d as files,h as homepage,g as license,p as main,i as name,j as peerDependencies,m as repository,a as scripts,s as type,r as types,n as version};//# sourceMappingURL=package-
|
|
3
|
-
//# sourceMappingURL=package-
|
|
1
|
+
var s="module",i="modelence",n="0.4.13",o="The Node.js Framework for Real-Time MongoDB Apps",p="dist/index.js",r="dist/global.d.ts",c={".":"./dist/index.js","./client":"./dist/client.js","./server":"./dist/server.js","./mongodb":"./dist/mongo.js"},d=["dist","dist/bin"],l={modelence:"./dist/bin/modelence.js"},a={build:"tsup",dev:"tsup --watch",prepublishOnly:"npm run build",test:'echo "Error: no test specified" && exit 1',postversion:"git push && git push --tags"},m={type:"git",url:"git+https://github.com/modelence/modelence.git"},u="Modelence",g="SEE LICENSE IN LICENSE",y={url:"https://github.com/modelence/modelence/issues"},h="https://modelence.com",b={"@types/archiver":"^6.0.3","@types/bcrypt":"^5.0.2","@types/express":"^5.0.0","@types/fs-extra":"^11.0.4","@types/node":"^22.5.1","@types/react":"^19.0.0","@types/react-dom":"^19.0.1","@typescript-eslint/eslint-plugin":"^8.17.0","@typescript-eslint/parser":"^8.17.0",react:"^19.0.0","react-dom":"^19.0.0",typescript:"^5.7.2"},v={"@octokit/rest":"^20.0.2","@tanstack/react-query":"^5.76.2","@vitejs/plugin-react":"^4.3.4",archiver:"^7.0.1",bcrypt:"^5.1.1",commander:"^12.0.0",dotenv:"^16.4.5","elastic-apm-node":"^4.8.0",express:"^4.21.0","fs-extra":"^11.2.0",jiti:"^2.4.2",mongodb:"^6.8.1",open:"^10.1.0",tsup:"^8.3.6",tsx:"^4.19.3",vite:"^6.0.3","vite-plugin-eslint":"^1.8.1",winston:"^3.15.0","winston-elasticsearch":"^0.19.0",zod:"^3.23.8",zustand:"^5.0.2"},j={react:">=18.0.0","react-dom":">=18.0.0"},x={type:s,name:i,version:n,description:o,main:p,types:r,exports:c,files:d,bin:l,scripts:a,repository:m,author:u,license:g,bugs:y,homepage:h,devDependencies:b,dependencies:v,peerDependencies:j};
|
|
2
|
+
export{u as author,l as bin,y as bugs,x as default,v as dependencies,o as description,b as devDependencies,c as exports,d as files,h as homepage,g as license,p as main,i as name,j as peerDependencies,m as repository,a as scripts,s as type,r as types,n as version};//# sourceMappingURL=package-4OSN27PP.js.map
|
|
3
|
+
//# sourceMappingURL=package-4OSN27PP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json"],"names":["type","name","version","description","main","types","exports","files","bin","scripts","repository","author","license","bugs","homepage","devDependencies","dependencies","peerDependencies","package_default"],"mappings":"AACE,IAAAA,EAAQ,QACRC,CAAAA,CAAAA,CAAQ,YACRC,CAAW,CAAA,QAAA,CACXC,EAAe,kDACfC,CAAAA,CAAAA,CAAQ,gBACRC,CAAS,CAAA,kBAAA,CACTC,EAAW,CACT,GAAA,CAAK,kBACL,UAAY,CAAA,kBAAA,CACZ,WAAY,kBACZ,CAAA,WAAA,CAAa,iBACf,CAAA,CACAC,EAAS,CACP,MAAA,CACA,UACF,CACAC,CAAAA,CAAAA,CAAO,CACL,SAAa,CAAA,yBACf,EACAC,CAAW,CAAA,CACT,MAAS,MACT,CAAA,GAAA,CAAO,eACP,cAAkB,CAAA,eAAA,CAClB,KAAQ,2CACR,CAAA,WAAA,CAAe,6BACjB,CAAA,CACAC,EAAc,CACZ,IAAA,CAAQ,MACR,GAAO,CAAA,gDACT,EACAC,CAAU,CAAA,WAAA,CACVC,EAAW,wBACXC,CAAAA,CAAAA,CAAQ,CACN,GAAO,CAAA,+CACT,EACAC,CAAY,CAAA,uBAAA,CACZC,EAAmB,CACjB,iBAAA,CAAmB,QACnB,CAAA,eAAA,CAAiB,SACjB,gBAAkB,CAAA,QAAA,CAClB,kBAAmB,SACnB,CAAA,aAAA,CAAe,UACf,cAAgB,CAAA,SAAA,CAChB,mBAAoB,SACpB,CAAA,kCAAA,CAAoC,UACpC,2BAA6B,CAAA,SAAA,CAC7B,MAAS,SACT,CAAA,WAAA,CAAa,UACb,UAAc,CAAA,QAChB,CACAC,CAAAA,CAAAA,CAAgB,CACd,eAAiB,CAAA,SAAA,CACjB,wBAAyB,SACzB,CAAA,sBAAA,CAAwB,SACxB,QAAY,CAAA,QAAA,CACZ,OAAU,QACV,CAAA,SAAA,CAAa,UACb,MAAU,CAAA,SAAA,CACV,mBAAoB,QACpB,CAAA,OAAA,CAAW,UACX,UAAY,CAAA,SAAA,CACZ,IAAQ,CAAA,QAAA,CACR,QAAW,QACX,CAAA,IAAA,CAAQ,UACR,IAAQ,CAAA,QAAA,CACR,IAAO,SACP,CAAA,IAAA,CAAQ,SACR,oBAAsB,CAAA,QAAA,CACtB,QAAW,SACX,CAAA,uBAAA,CAAyB,UACzB,GAAO,CAAA,SAAA,CACP,QAAW,QACb,CAAA,CACAC,CAAoB,CAAA,CAClB,MAAS,UACT,CAAA,WAAA,CAAa,UACf,CA7EFC,CAAAA,CAAAA,CAAA,CACE,IAAAlB,CAAAA,CAAAA,CACA,KAAAC,CACA,CAAA,OAAA,CAAAC,EACA,WAAAC,CAAAA,CAAAA,CACA,KAAAC,CACA,CAAA,KAAA,CAAAC,EACA,OAAAC,CAAAA,CAAAA,CAMA,KAAAC,CAAAA,CAAAA,CAIA,IAAAC,CAGA,CAAA,OAAA,CAAAC,EAOA,UAAAC,CAAAA,CAAAA,CAIA,OAAAC,CACA,CAAA,OAAA,CAAAC,EACA,IAAAC,CAAAA,CAAAA,CAGA,SAAAC,CACA,CAAA,eAAA,CAAAC,EAcA,YAAAC,CAAAA,CAAAA,CAuBA,iBAAAC,CAIF","file":"package-
|
|
1
|
+
{"version":3,"sources":["../package.json"],"names":["type","name","version","description","main","types","exports","files","bin","scripts","repository","author","license","bugs","homepage","devDependencies","dependencies","peerDependencies","package_default"],"mappings":"AACE,IAAAA,EAAQ,QACRC,CAAAA,CAAAA,CAAQ,YACRC,CAAW,CAAA,QAAA,CACXC,EAAe,kDACfC,CAAAA,CAAAA,CAAQ,gBACRC,CAAS,CAAA,kBAAA,CACTC,EAAW,CACT,GAAA,CAAK,kBACL,UAAY,CAAA,kBAAA,CACZ,WAAY,kBACZ,CAAA,WAAA,CAAa,iBACf,CAAA,CACAC,EAAS,CACP,MAAA,CACA,UACF,CACAC,CAAAA,CAAAA,CAAO,CACL,SAAa,CAAA,yBACf,EACAC,CAAW,CAAA,CACT,MAAS,MACT,CAAA,GAAA,CAAO,eACP,cAAkB,CAAA,eAAA,CAClB,KAAQ,2CACR,CAAA,WAAA,CAAe,6BACjB,CAAA,CACAC,EAAc,CACZ,IAAA,CAAQ,MACR,GAAO,CAAA,gDACT,EACAC,CAAU,CAAA,WAAA,CACVC,EAAW,wBACXC,CAAAA,CAAAA,CAAQ,CACN,GAAO,CAAA,+CACT,EACAC,CAAY,CAAA,uBAAA,CACZC,EAAmB,CACjB,iBAAA,CAAmB,QACnB,CAAA,eAAA,CAAiB,SACjB,gBAAkB,CAAA,QAAA,CAClB,kBAAmB,SACnB,CAAA,aAAA,CAAe,UACf,cAAgB,CAAA,SAAA,CAChB,mBAAoB,SACpB,CAAA,kCAAA,CAAoC,UACpC,2BAA6B,CAAA,SAAA,CAC7B,MAAS,SACT,CAAA,WAAA,CAAa,UACb,UAAc,CAAA,QAChB,CACAC,CAAAA,CAAAA,CAAgB,CACd,eAAiB,CAAA,SAAA,CACjB,wBAAyB,SACzB,CAAA,sBAAA,CAAwB,SACxB,QAAY,CAAA,QAAA,CACZ,OAAU,QACV,CAAA,SAAA,CAAa,UACb,MAAU,CAAA,SAAA,CACV,mBAAoB,QACpB,CAAA,OAAA,CAAW,UACX,UAAY,CAAA,SAAA,CACZ,IAAQ,CAAA,QAAA,CACR,QAAW,QACX,CAAA,IAAA,CAAQ,UACR,IAAQ,CAAA,QAAA,CACR,IAAO,SACP,CAAA,IAAA,CAAQ,SACR,oBAAsB,CAAA,QAAA,CACtB,QAAW,SACX,CAAA,uBAAA,CAAyB,UACzB,GAAO,CAAA,SAAA,CACP,QAAW,QACb,CAAA,CACAC,CAAoB,CAAA,CAClB,MAAS,UACT,CAAA,WAAA,CAAa,UACf,CA7EFC,CAAAA,CAAAA,CAAA,CACE,IAAAlB,CAAAA,CAAAA,CACA,KAAAC,CACA,CAAA,OAAA,CAAAC,EACA,WAAAC,CAAAA,CAAAA,CACA,KAAAC,CACA,CAAA,KAAA,CAAAC,EACA,OAAAC,CAAAA,CAAAA,CAMA,KAAAC,CAAAA,CAAAA,CAIA,IAAAC,CAGA,CAAA,OAAA,CAAAC,EAOA,UAAAC,CAAAA,CAAAA,CAIA,OAAAC,CACA,CAAA,OAAA,CAAAC,EACA,IAAAC,CAAAA,CAAAA,CAGA,SAAAC,CACA,CAAA,eAAA,CAAAC,EAcA,YAAAC,CAAAA,CAAAA,CAuBA,iBAAAC,CAIF","file":"package-4OSN27PP.js","sourcesContent":["{\n \"type\": \"module\",\n \"name\": \"modelence\",\n \"version\": \"0.4.13\",\n \"description\": \"The Node.js Framework for Real-Time MongoDB Apps\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/global.d.ts\",\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./client\": \"./dist/client.js\",\n \"./server\": \"./dist/server.js\",\n \"./mongodb\": \"./dist/mongo.js\"\n },\n \"files\": [\n \"dist\",\n \"dist/bin\"\n ],\n \"bin\": {\n \"modelence\": \"./dist/bin/modelence.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"prepublishOnly\": \"npm run build\",\n \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n \"postversion\": \"git push && git push --tags\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/modelence/modelence.git\"\n },\n \"author\": \"Modelence\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"bugs\": {\n \"url\": \"https://github.com/modelence/modelence/issues\"\n },\n \"homepage\": \"https://modelence.com\",\n \"devDependencies\": {\n \"@types/archiver\": \"^6.0.3\",\n \"@types/bcrypt\": \"^5.0.2\",\n \"@types/express\": \"^5.0.0\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^22.5.1\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.1\",\n \"@typescript-eslint/eslint-plugin\": \"^8.17.0\",\n \"@typescript-eslint/parser\": \"^8.17.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"typescript\": \"^5.7.2\"\n },\n \"dependencies\": {\n \"@octokit/rest\": \"^20.0.2\",\n \"@tanstack/react-query\": \"^5.76.2\",\n \"@vitejs/plugin-react\": \"^4.3.4\",\n \"archiver\": \"^7.0.1\",\n \"bcrypt\": \"^5.1.1\",\n \"commander\": \"^12.0.0\",\n \"dotenv\": \"^16.4.5\",\n \"elastic-apm-node\": \"^4.8.0\",\n \"express\": \"^4.21.0\",\n \"fs-extra\": \"^11.2.0\",\n \"jiti\": \"^2.4.2\",\n \"mongodb\": \"^6.8.1\",\n \"open\": \"^10.1.0\",\n \"tsup\": \"^8.3.6\",\n \"tsx\": \"^4.19.3\",\n \"vite\": \"^6.0.3\",\n \"vite-plugin-eslint\": \"^1.8.1\",\n \"winston\": \"^3.15.0\",\n \"winston-elasticsearch\": \"^0.19.0\",\n \"zod\": \"^3.23.8\",\n \"zustand\": \"^5.0.2\"\n },\n \"peerDependencies\": {\n \"react\": \">=18.0.0\",\n \"react-dom\": \">=18.0.0\"\n }\n}\n"]}
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import {a as a$2}from'./chunk-DN5SVAO2.js';import {a as a$3,b as b$1}from'./chunk-EQLDF7OO.js';import {a as a$1}from'./chunk-R7MPLJMA.js';import at from'dotenv';import It from'http';import G from'express';import w,{z}from'zod';import pt from'elastic-apm-node';import W from'winston';import {ElasticsearchTransport}from'winston-elasticsearch';import T from'process';import {ObjectId,MongoClient}from'mongodb';export{ObjectId}from'mongodb';import {randomBytes}from'crypto';import Dt from'bcrypt';import jt from'os';import {createServer,defineConfig}from'vite';import Bt from'@vitejs/plugin-react';import te from'path';import Ft from'fs';function ct(){return typeof window!="object"}function b(){if(!ct())throw new Error("This function can only be called on the server")}var B={},F={},se=false;function C(t){return F[t]?.value}function ae(){if(!se)throw new Error("Config is not initialized: an attempt was made to access configs before they were loaded");return Object.fromEntries(Object.entries(F).filter(([t])=>B[t]?.isPublic))}function I(t){t.forEach(({key:e,type:o,value:n})=>{!e.toLowerCase().startsWith("_system.")&&!B[e]||(F[e]={key:e,type:o,value:n});}),se=true;}function ce(t){Object.entries(t).forEach(([e,o])=>{let{type:n,isPublic:i}=o;if(e.toLowerCase().startsWith("_system."))throw new Error(`Config key cannot start with a reserved prefix: '_system.' (${e})`);if(n==="secret"&&i)throw new Error(`Config ${e} with type "secret" cannot be public`)}),B=t;}var E=null;function de(t){E=Object.assign({},E,t);}function ue(){return E?.deploymentId}function pe(){return E?.appAlias}function me(){return E?.deploymentAlias}function fe(){return E?.telemetry?.serviceName}function S(){return !!E?.telemetry?.isEnabled}function P(t,e){S()&&K().info(t,e);}function he(t,e){S()&&K().error(t,e);}var h={stdout:[{log:"",timestamp:null}],stderr:[{log:"",timestamp:null}]},dt=1;function ye({elasticCloudId:t,elasticApiKey:e}){let o=T.stdout.write,n=T.stderr.write;T.stdout.write=function(i,...r){return ge(i.toString(),h.stdout),o.call(T.stdout,i,...r)},T.stderr.write=function(i,...r){return ge(i.toString(),h.stderr),n.call(T.stderr,i,...r)},we();}function ge(t,e){if(t.length===0)return;let o=new Date;for(let n=0;n<t.length;n++){let i=e[e.length-1];i.timestamp||(i.timestamp=o,i.sequenceId=dt++),t[n]===`
|
|
2
|
-
`?e.push({log:"",timestamp:null}):i.log+=t[n];}}async function ut(){let t=h.stdout.slice(0,-1);h.stdout=[h.stdout[h.stdout.length-1]];let e=h.stderr.slice(0,-1);h.stderr=[h.stderr[h.stderr.length-1]],t.forEach(({log:o,timestamp:n,sequenceId:i})=>{P(o,{timestamp:n,source:"console",sequenceId:i});}),e.forEach(({log:o,timestamp:n,sequenceId:i})=>{he(o,{timestamp:n,source:"console",sequenceId:i});});}function we(){setTimeout(()=>{ut(),we();},1e3);}var be=false,x=null,V=null,Ce=async()=>{if(be)throw new Error('Metrics are already initialized, duplicate "initMetrics" call received');be=true,S()&&await ft();};async function ft(){let t=C("_system.elastic.apmEndpoint"),e=C("_system.elastic.cloudId"),o=C("_system.elastic.apiKey"),n=pe()??"unknown",i=me()??"unknown",r=ue()??"unknown",s=fe();x=pt.start({serviceName:s,apiKey:o,serverUrl:t,transactionSampleRate:1,centralConfig:false,globalLabels:{modelenceEnv:"dev",appEnv:"dev",deploymentId:r,appAlias:n,deploymentAlias:i}});let c=new ElasticsearchTransport({apm:x,level:"debug",clientOpts:{cloud:{id:e},auth:{apiKey:o},requestTimeout:1e4,tls:{rejectUnauthorized:false}},bufferLimit:1e3,silent:false});c.on("error",u=>{console.error("Elasticsearch Transport Error:",u);}),V=W.createLogger({level:"debug",defaultMeta:{serviceName:s},format:W.format.combine(W.format.json()),transports:[c]}),ye({elasticCloudId:e,elasticApiKey:o});}function $(t,e,o){if(!S())return {end:()=>{}};if(!x)throw new Error("startTransaction: Elastic APM is not initialized");let n=x.startTransaction(e,t);return o&&x.setCustomContext(o),n}function Ee(t){if(!S()){console.error(t);return}if(!x)throw new Error("captureError: Elastic APM is not initialized");x.captureError(t);}function K(){if(!V)throw new Error("Logger is not initialized");return V}var Se=new Map,D={authenticated:null,unauthenticated:null};function xe(t,e){D.authenticated=e.authenticated,D.unauthenticated=e.unauthenticated;for(let[o,n]of Object.entries(t))Se.set(o,n);}function k(){return D.unauthenticated?[D.unauthenticated]:[]}function Me(){return D.authenticated?[D.authenticated]:[]}function Te(t,e){let o=e.find(n=>!ht(t,n));if(o)throw new Error(`Access denied - missing permission: '${o}'`)}function ht(t,e){for(let o of t){let n=Se.get(o);if(n&&n.permissions.includes(e))return true}return false}var H={};function Z(t,e){return b(),Oe(t),N("query",t,e)}function De(t,e){return b(),Oe(t),N("mutation",t,e)}function ve(t,e){return b(),Ie(t),N("query",t,e)}function Re(t,e){return b(),Ie(t),N("mutation",t,e)}function Oe(t){if(t.toLowerCase().startsWith("_system."))throw new Error(`Method name cannot start with a reserved prefix: '_system.' (${t})`)}function Ie(t){if(!t.toLowerCase().startsWith("_system."))throw new Error(`System method name must start with a prefix: '_system.' (${t})`)}function N(t,e,o){if(b(),H[e])throw new Error(`Method with name '${e}' is already defined.`);let n=typeof o=="function"?o:o.handler,i=typeof o=="function"?[]:o.permissions??[];H[e]={type:t,name:e,handler:n,permissions:i};}async function Ae(t,e,o){b();let n=H[t];if(!n)throw new Error(`Method with name '${t}' is not defined.`);let{type:i,handler:r}=n,s=$("method",`method:${t}`,{type:i,args:e}),c;try{Te(o.roles,n.permissions),c=await r(e,o);}catch(u){throw s.end("error"),u}return s.end(),c}var m=class{constructor(e,{stores:o=[],queries:n={},mutations:i={},routes:r=[],cronJobs:s={},configSchema:c={}}){this.name=e,this.stores=o,this.queries=n,this.mutations=i,this.routes=r,this.cronJobs=s,this.configSchema=c;}};var f=class{constructor(e,o){this.name=e,this.schema=o.schema,this.methods=o.methods,this.indexes=o.indexes;}getName(){return this.name}getSchema(){return this.schema}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(){this.indexes.length>0&&await this.requireCollection().createIndexes(this.indexes);}wrapDocument(e){return this.methods?Object.create(null,Object.getOwnPropertyDescriptors({...e,...this.methods})):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,o){let n=await this.requireCollection().findOne(e,o);return n?this.wrapDocument(n):null}async requireOne(e,o,n){let i=await this.findOne(e,o);if(!i)throw n?n():new Error(`Record not found in ${this.name}`);return i}find(e,o){let n=this.requireCollection().find(e);return o?.sort&&n.sort(o.sort),o?.limit&&n.limit(o.limit),o?.skip&&n.skip(o.skip),n}async findById(e){let o=typeof e=="string"?{_id:new ObjectId(e)}:{_id:e};return await this.findOne(o)}async requireById(e,o){let n=await this.findById(e);if(!n)throw o?o():new Error(`Record with id ${e} not found in ${this.name}`);return n}async fetch(e,o){return (await this.find(e,o).toArray()).map(this.wrapDocument.bind(this))}async insertOne(e){return await this.requireCollection().insertOne(e)}async insertMany(e){return await this.requireCollection().insertMany(e)}async updateOne(e,o){let n=typeof e=="string"?{_id:new ObjectId(e)}:e;return await this.requireCollection().updateOne(n,o)}async upsertOne(e,o){return await this.requireCollection().updateOne(e,o,{upsert:true})}async updateMany(e,o,n){return await this.requireCollection().updateMany(e,o,n)}async upsertMany(e,o){return await this.requireCollection().updateMany(e,o,{upsert:true})}async deleteOne(e){return await this.requireCollection().deleteOne(e)}async deleteMany(e){return await this.requireCollection().deleteMany(e)}aggregate(e,o){return this.requireCollection().aggregate(e,o)}bulkWrite(e){return this.requireCollection().bulkWrite(e)}getDatabase(){return this.requireClient().db()}rawCollection(){return this.requireCollection()}async renameFrom(e,o){let n=this.getDatabase();if(!this.collection||!n)throw new Error(`Store ${this.name} is not provisioned`);if((await n.listCollections({name:e}).toArray()).length===0)throw new Error(`Collection ${e} not found`);if((await n.listCollections({name:this.name}).toArray()).length>0)throw new Error(`Collection ${this.name} already exists`);await n.collection(e).rename(this.name,o);}};var gt=z.string.bind(z),yt=z.number.bind(z),wt=z.date.bind(z),bt=z.boolean.bind(z),Ct=z.array.bind(z),Et=z.object.bind(z),St=z.enum.bind(z),a={string:gt,number:yt,date:wt,boolean:bt,array:Ct,object:Et,enum:St,objectId(){return z.instanceof(ObjectId)},userId(){return z.instanceof(ObjectId)},ref(t){return z.instanceof(ObjectId)},union:z.union.bind(z),infer(t){return {}}};var v=new f("_modelenceSessions",{schema:{authToken:a.string(),createdAt:a.date(),expiresAt:a.date(),userId:a.userId().nullable()},indexes:[{key:{authToken:1},unique:true},{key:{expiresAt:1}}]});async function je(t){let e=t?await v.findOne({authToken:t}):null;return e?{authToken:String(e.authToken),expiresAt:new Date(e.expiresAt),userId:e.userId??null}:await Mt()}async function Pe(t,e){await v.updateOne({authToken:t},{$set:{userId:e}});}async function $e(t){await v.updateOne({authToken:t},{$set:{userId:null}});}async function Mt(){let t=randomBytes(32).toString("base64url"),e=Date.now(),o=new Date(e+a$1.days(7));return await v.insertOne({authToken:t,createdAt:new Date(e),expiresAt:o,userId:null}),{authToken:t,expiresAt:o,userId:null}}async function Tt(t){let e=Date.now(),o=new Date(e+a$1.days(7));await v.updateOne({authToken:t.authToken},{$set:{lastActiveDate:new Date(e),expiresAt:o}});}var ke=new m("_system.session",{stores:[v],mutations:{init:async function(t,{session:e,user:o}){return {session:e,user:o,configs:ae()}},heartbeat:async function(t,{session:e}){e&&await Tt(e);}}});async function Ue(t,{user:e}){let o=z.string().email().parse(t.email),n=z.string().min(8,{message:"Password must contain at least 8 characters"}).parse(t.password),i=await g.findOne({"emails.address":o},{collation:{locale:"en",strength:2}});if(i){let c=i.emails?.find(u=>u.address===o);throw new Error(`User with email already exists: ${c?.address}`)}let r=await Dt.hash(n,10);return (await g.insertOne({handle:o,emails:[{address:o,verified:false}],createdAt:new Date,authMethods:{password:{hash:r}}})).insertedId}async function Je(t,{user:e,session:o}){if(!o)throw new Error("Session is not initialized");let n=z.string().email().parse(t.email),i=z.string().parse(t.password),r=await g.findOne({"emails.address":n},{collation:{locale:"en",strength:2}}),s=r?.authMethods?.password?.hash;if(!r||!s||!await Dt.compare(i,s))throw ze();return await Pe(o.authToken,r._id),{user:{id:r._id,handle:r.handle}}}async function qe(t,{user:e,session:o}){if(!o)throw new Error("Session is not initialized");await $e(o.authToken);}function ze(){return new Error("Incorrect email/password combination")}var g=new f("_modelenceUsers",{schema:{handle:a.string(),emails:a.array(a.object({address:a.string(),verified:a.boolean()})).optional(),createdAt:a.date(),authMethods:a.object({password:a.object({hash:a.string()}).optional(),google:a.object({id:a.string()}).optional()})},indexes:[{key:{handle:1},unique:true,collation:{locale:"en",strength:2}}]});var Be=new m("_system.user",{stores:[g],mutations:{signupWithPassword:Ue,loginWithPassword:Je,logout:qe}});async function Fe(t){let e=await je(t),o=e.userId?await g.findOne({_id:new ObjectId(e.userId)}):null,n=o?{id:o._id.toString(),handle:o.handle}:null,i=n?Me():k();return {user:n,session:e,roles:i}}function Ke(t){return async(e,o)=>{try{let n=await t({query:e.query,body:e.body,params:e.params,headers:e.headers,cookies:e.cookies,req:e});o.status(n.status||200),n.headers&&Object.entries(n.headers).forEach(([i,r])=>{o.setHeader(i,r);}),o.send(n.data);}catch(n){n instanceof a$3||n instanceof b$1?o.status(n.status).send(n.message):(console.error(`Error in route handler: ${e.path}`),console.error(n),o.status(500).send(String(n)));}}}var y=null;async function We(){if(y)return y;let t=A();if(!t)throw new Error("MongoDB URI is not set");y=new MongoClient(t,{maxPoolSize:20});try{return await y.connect(),await y.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),y}catch(e){throw console.error(e),y=null,e}}function A(){let t=C("_system.mongodbUri");return t?String(t):void 0}function Ve(){return y}function At(t,e){for(let o of e)for(let n of o.routes){let{path:i,handlers:r}=n;Object.entries(r).forEach(([s,c])=>{t[s](i,Ke(c));});}}async function He(t,{combinedModules:e}){let o=G();o.use(G.json()),o.use(G.urlencoded({extended:true})),o.post("/api/_internal/method/:methodName(*)",async(r,s)=>{let{methodName:c}=r.params,u=await _t(r);try{let d=await Ae(c,r.body.args,u);s.json({data:d,typeMap:a$2(d)});}catch(d){if(console.error(`Error in method ${c}:`,d),d instanceof Error&&d?.constructor?.name==="ZodError"&&"errors"in d){let R=d.flatten(),O=Object.entries(R.fieldErrors).map(([J,q])=>`${J}: ${(q??[]).join(", ")}`).join("; "),L=R.formErrors.join("; "),z=[O,L].filter(Boolean).join("; ");s.status(400).send(z);}else s.status(500).send(d instanceof Error?d.message:String(d));}}),At(o,e),await t.init(),t.middlewares&&o.use(t.middlewares()),o.all("*",(r,s)=>t.handler(r,s)),process.on("unhandledRejection",(r,s)=>{console.error("Unhandled Promise Rejection:"),console.error(r instanceof Error?r.stack:r),console.error("Promise:",s);}),process.on("uncaughtException",r=>{console.error("Uncaught Exception:"),console.error(r.stack),console.trace("Full application stack:");});let n=It.createServer(o),i=process.env.PORT||3e3;n.listen(i,()=>{P("Application started",{source:"app"}),console.log(`Application started on port ${i}`);});}async function _t(t){let e=w.string().nullish().transform(r=>r??null).parse(t.body.authToken),o=w.object({screenWidth:w.number(),screenHeight:w.number(),windowWidth:w.number(),windowHeight:w.number(),pixelRatio:w.number(),orientation:w.string().nullable()}).parse(t.body.clientInfo),n={ip:t.ip||t.socket.remoteAddress,userAgent:t.get("user-agent"),acceptLanguage:t.get("accept-language"),referrer:t.get("referrer")};if(!!A()){let{session:r,user:s,roles:c}=await Fe(e);return {clientInfo:o,connectionInfo:n,session:r,user:s,roles:c}}return {clientInfo:o,connectionInfo:n,session:null,user:null,roles:k()}}async function Ze({configSchema:t,cronJobsMetadata:e,stores:o}){let n=process.env.MODELENCE_CONTAINER_ID;if(!n)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");try{let i=Object.values(o).map(s=>({name:s.getName(),schema:s.getSchema(),collections:[s.getName()]})),r=await Y("/api/connect","POST",{hostname:jt.hostname(),containerId:n,dataModels:i,configSchema:t,cronJobsMetadata:e});return console.log("Successfully connected to Modelence Cloud"),r}catch(i){throw console.error("Unable to connect to Modelence Cloud:",i),i}}async function Qe(){return await Y("/api/configs","GET")}async function Ge(){return await Y("/api/sync","POST",{containerId:process.env.MODELENCE_CONTAINER_ID})}async function Y(t,e,o){let{MODELENCE_SERVICE_ENDPOINT:n,MODELENCE_SERVICE_TOKEN:i}=process.env;if(!n)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set");let r=await fetch(`${n}${t}`,{method:e,headers:{Authorization:`Bearer ${i}`,...o?{"Content-Type":"application/json"}:{}},body:o?JSON.stringify(o):void 0});if(!r.ok){let s=await r.text();try{let c=JSON.parse(s);throw new Error(`Unable to connect to Modelence Cloud: HTTP status: ${r.status}, ${c?.error}`)}catch{throw new Error(`Unable to connect to Modelence Cloud: HTTP status: ${r.status}, ${s}`)}}return await r.json()}var X=false,Pt=a$1.seconds(10);function Ye(){setInterval(async()=>{if(!X){X=true;try{await Ge();}catch(t){console.error("Error syncing status",t);}try{await $t();}catch(t){console.error("Error syncing config",t);}X=false;}},Pt);}async function $t(){let{configs:t}=await Qe();I(t);}var U=new f("_modelenceMigrations",{schema:{version:a.number(),appliedAt:a.date()},indexes:[{key:{version:1},unique:true}]});async function Xe(t){if(t.length===0)return;let e=t.map(({version:r})=>r),o=await U.fetch({version:{$in:e}}),n=new Set(o.map(({version:r})=>r)),i=t.filter(({version:r})=>!n.has(r));if(i.length!==0){console.log(`Running migrations (${i.length})...`);for(let{version:r,description:s,handler:c}of i)console.log(`Running migration v${r}: ${s}`),await U.insertOne({version:r,appliedAt:new Date}),await c(),console.log(`Migration v${r} complete`);}}var et=new m("_system.migration",{stores:[U]});var kt=a$1.minutes(1),Nt=a$1.seconds(10),M={},ee,_=new f("_modelenceCronJobs",{schema:{alias:a.string(),lastStartDate:a.date().optional(),lock:a.object({containerId:a.string(),acquireDate:a.date()}).optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function ot(t,{description:e="",interval:o,timeout:n=kt,handler:i}){if(M[t])throw new Error(`Duplicate cron job declaration: '${t}' already exists`);if(ee)throw new Error(`Unable to add a cron job - cron jobs have already been initialized: [${t}]`);if(o<a$1.seconds(5))throw new Error(`Cron job interval should not be less than 5 second [${t}]`);if(n>a$1.days(1))throw new Error(`Cron job timeout should not be longer than 1 day [${t}]`);M[t]={alias:t,params:{description:e,interval:o,timeout:n},handler:i,state:{isRunning:false}};}async function nt(){if(ee)throw new Error("Cron jobs already started");let t=Object.keys(M);if(t.length>0){let e={alias:{$in:t}},o=await _.findOne({...e,"lock.containerId":{$exists:true}});await _.upsertMany(e,{$set:{lock:{containerId:process.env.MODELENCE_CONTAINER_ID||"unknown",acquireDate:new Date}}}),o&&await Ut(Nt);let n=await _.fetch(e),i=Date.now();n.forEach(r=>{let s=M[r.alias];s&&(s.state.scheduledRunTs=r.lastStartDate?r.lastStartDate.getTime()+s.params.interval:i);}),Object.values(M).forEach(r=>{r.state.scheduledRunTs||(r.state.scheduledRunTs=i);}),ee=setInterval(Lt,a$1.seconds(1));}}function Ut(t){return new Promise(e=>setTimeout(e,t))}async function Lt(){let t=Date.now();Object.values(M).forEach(async e=>{let{params:o,state:n}=e;if(n.isRunning){n.startTs&&n.startTs+o.timeout<t&&(n.isRunning=false);return}n.scheduledRunTs&&n.scheduledRunTs<=t&&await zt(e);});}async function zt(t){let{alias:e,params:o,handler:n,state:i}=t;i.isRunning=true,i.startTs=Date.now();let r=$("cron",`cron:${e}`);n().then(()=>{tt(i,o),r.end("success");}).catch(s=>{tt(i,o),Ee(s),r.end("error"),console.error(`Error in cron job '${e}':`,s);}),await _.updateOne({alias:e},{$set:{lastStartDate:new Date(i.startTs)}});}function tt(t,e){t.scheduledRunTs=t.startTs?t.startTs+e.interval:Date.now(),t.startTs=void 0,t.isRunning=false;}function rt(){return Object.values(M).map(({alias:t,params:e})=>({alias:t,description:e.description,interval:e.interval,timeout:e.timeout}))}var it=new m("_system.cron",{stores:[_]});var oe=class{async init(){this.isDev()&&(console.log("Starting Vite dev server..."),this.viteServer=await createServer({...defineConfig(await Wt()),server:{middlewareMode:true},root:"./src/client"}));}middlewares(){return this.isDev()?this.viteServer?.middlewares??[]:[G.static("./.modelence/build/client")]}handler(e,o){if(this.isDev())try{o.sendFile("index.html",{root:"./src/client"});}catch(n){console.error("Error serving index.html:",n),o.status(500).send("Internal Server Error");}else o.sendFile("index.html",{root:"./.modelence/build/client"});}isDev(){return process.env.NODE_ENV!=="production"}};async function Wt(){let t=process.cwd(),e=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(n=>Ft.existsSync(te.join(t,n))),o=[Bt(),Vt()];if(e){let n=(await import('vite-plugin-eslint')).default;o.push(n({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:t,overrideConfigFile:te.resolve(t,e)}));}return {plugins:o,root:t,build:{outDir:".modelence/build/client",emptyOutDir:true},server:{proxy:{"/api":"http://localhost:4000"},headers:{"Cache-Control":"no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0",Pragma:"no-cache",Expires:"0"},hmr:{port:0}},resolve:{alias:{"@":te.resolve(t,"src")}}}}function Vt(){return {name:"modelence-asset-handler",async transform(t,e){if(/\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/.test(e))return process.env.NODE_ENV==="development",t},async generateBundle(t,e){}}}var st=new oe;async function Ht({modules:t=[],roles:e={},defaultRoles:o={},server:n=st,migrations:i=[]}){at.config(),at.config({path:".modelence.env"});let r=!!process.env.MODELENCE_SERVICE_ENDPOINT,s=process.env.MODELENCE_CRON_ENABLED==="true";oo().then(()=>{}).catch(()=>{});let c=[Be,ke,it,et],u=[...c,...t];Qt(c),Zt(t),xe(e,o);let d=Yt(u);ce(d??{});let j=Gt(u);if(s&&Xt(u),r){let{configs:O,deploymentId:L,appAlias:z,deploymentAlias:J,telemetry:q}=await Ze({configSchema:d,cronJobsMetadata:s?rt():void 0,stores:j});I(O),de({deploymentId:L,appAlias:z,deploymentAlias:J,telemetry:q});}else I(to());let R=A();if(R&&(await We(),eo(j)),s&&await Xe(i),R)for(let O of j)O.createIndexes();r&&(await Ce(),Ye()),s&&nt().catch(console.error),await He(n,{combinedModules:u});}function Zt(t){for(let e of t){for(let[o,n]of Object.entries(e.queries))Z(`${e.name}.${o}`,n);for(let[o,n]of Object.entries(e.mutations))De(`${e.name}.${o}`,n);}}function Qt(t){for(let e of t){for(let[o,n]of Object.entries(e.queries))ve(`${e.name}.${o}`,n);for(let[o,n]of Object.entries(e.mutations))Re(`${e.name}.${o}`,n);}}function Gt(t){return t.flatMap(e=>e.stores)}function Yt(t){let e={};for(let o of t)for(let[n,i]of Object.entries(o.configSchema)){let r=`${o.name}.${n}`;if(r in e)throw new Error(`Duplicate config schema key: ${r} (${o.name})`);e[r]=i;}return e}function Xt(t){for(let e of t)for(let[o,n]of Object.entries(e.cronJobs))ot(`${e.name}.${o}`,n);}function eo(t){let e=Ve();if(!e)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let o of t)o.init(e);}function to(){let t=[];return process.env.MONGODB_URI&&t.push({key:"_system.mongodbUri",type:"string",value:process.env.MONGODB_URI}),t}async function oo(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let e=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",o=await import('./package-DF3VLPXG.js');await fetch(`${e}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({version:o.default.version})});}}
|
|
2
|
+
`?e.push({log:"",timestamp:null}):i.log+=t[n];}}async function ut(){let t=h.stdout.slice(0,-1);h.stdout=[h.stdout[h.stdout.length-1]];let e=h.stderr.slice(0,-1);h.stderr=[h.stderr[h.stderr.length-1]],t.forEach(({log:o,timestamp:n,sequenceId:i})=>{P(o,{timestamp:n,source:"console",sequenceId:i});}),e.forEach(({log:o,timestamp:n,sequenceId:i})=>{he(o,{timestamp:n,source:"console",sequenceId:i});});}function we(){setTimeout(()=>{ut(),we();},1e3);}var be=false,x=null,V=null,Ce=async()=>{if(be)throw new Error('Metrics are already initialized, duplicate "initMetrics" call received');be=true,S()&&await ft();};async function ft(){let t=C("_system.elastic.apmEndpoint"),e=C("_system.elastic.cloudId"),o=C("_system.elastic.apiKey"),n=pe()??"unknown",i=me()??"unknown",r=ue()??"unknown",s=fe();x=pt.start({serviceName:s,apiKey:o,serverUrl:t,transactionSampleRate:1,centralConfig:false,globalLabels:{modelenceEnv:"dev",appEnv:"dev",deploymentId:r,appAlias:n,deploymentAlias:i}});let c=new ElasticsearchTransport({apm:x,level:"debug",clientOpts:{cloud:{id:e},auth:{apiKey:o},requestTimeout:1e4,tls:{rejectUnauthorized:false}},bufferLimit:1e3,silent:false});c.on("error",u=>{console.error("Elasticsearch Transport Error:",u);}),V=W.createLogger({level:"debug",defaultMeta:{serviceName:s},format:W.format.combine(W.format.json()),transports:[c]}),ye({elasticCloudId:e,elasticApiKey:o});}function $(t,e,o){if(!S())return {end:()=>{}};if(!x)throw new Error("startTransaction: Elastic APM is not initialized");let n=x.startTransaction(e,t);return o&&x.setCustomContext(o),n}function Ee(t){if(!S()){console.error(t);return}if(!x)throw new Error("captureError: Elastic APM is not initialized");x.captureError(t);}function K(){if(!V)throw new Error("Logger is not initialized");return V}var Se=new Map,D={authenticated:null,unauthenticated:null};function xe(t,e){D.authenticated=e.authenticated,D.unauthenticated=e.unauthenticated;for(let[o,n]of Object.entries(t))Se.set(o,n);}function k(){return D.unauthenticated?[D.unauthenticated]:[]}function Me(){return D.authenticated?[D.authenticated]:[]}function Te(t,e){let o=e.find(n=>!ht(t,n));if(o)throw new Error(`Access denied - missing permission: '${o}'`)}function ht(t,e){for(let o of t){let n=Se.get(o);if(n&&n.permissions.includes(e))return true}return false}var H={};function Z(t,e){return b(),Oe(t),N("query",t,e)}function De(t,e){return b(),Oe(t),N("mutation",t,e)}function ve(t,e){return b(),Ie(t),N("query",t,e)}function Re(t,e){return b(),Ie(t),N("mutation",t,e)}function Oe(t){if(t.toLowerCase().startsWith("_system."))throw new Error(`Method name cannot start with a reserved prefix: '_system.' (${t})`)}function Ie(t){if(!t.toLowerCase().startsWith("_system."))throw new Error(`System method name must start with a prefix: '_system.' (${t})`)}function N(t,e,o){if(b(),H[e])throw new Error(`Method with name '${e}' is already defined.`);let n=typeof o=="function"?o:o.handler,i=typeof o=="function"?[]:o.permissions??[];H[e]={type:t,name:e,handler:n,permissions:i};}async function Ae(t,e,o){b();let n=H[t];if(!n)throw new Error(`Method with name '${t}' is not defined.`);let{type:i,handler:r}=n,s=$("method",`method:${t}`,{type:i,args:e}),c;try{Te(o.roles,n.permissions),c=await r(e,o);}catch(u){throw s.end("error"),u}return s.end(),c}var m=class{constructor(e,{stores:o=[],queries:n={},mutations:i={},routes:r=[],cronJobs:s={},configSchema:c={}}){this.name=e,this.stores=o,this.queries=n,this.mutations=i,this.routes=r,this.cronJobs=s,this.configSchema=c;}};var f=class{constructor(e,o){this.name=e,this.schema=o.schema,this.methods=o.methods,this.indexes=o.indexes;}getName(){return this.name}getSchema(){return this.schema}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(){this.indexes.length>0&&await this.requireCollection().createIndexes(this.indexes);}wrapDocument(e){return this.methods?Object.create(null,Object.getOwnPropertyDescriptors({...e,...this.methods})):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,o){let n=await this.requireCollection().findOne(e,o);return n?this.wrapDocument(n):null}async requireOne(e,o,n){let i=await this.findOne(e,o);if(!i)throw n?n():new Error(`Record not found in ${this.name}`);return i}find(e,o){let n=this.requireCollection().find(e);return o?.sort&&n.sort(o.sort),o?.limit&&n.limit(o.limit),o?.skip&&n.skip(o.skip),n}async findById(e){let o=typeof e=="string"?{_id:new ObjectId(e)}:{_id:e};return await this.findOne(o)}async requireById(e,o){let n=await this.findById(e);if(!n)throw o?o():new Error(`Record with id ${e} not found in ${this.name}`);return n}async fetch(e,o){return (await this.find(e,o).toArray()).map(this.wrapDocument.bind(this))}async insertOne(e){return await this.requireCollection().insertOne(e)}async insertMany(e){return await this.requireCollection().insertMany(e)}async updateOne(e,o){let n=typeof e=="string"?{_id:new ObjectId(e)}:e;return await this.requireCollection().updateOne(n,o)}async upsertOne(e,o){return await this.requireCollection().updateOne(e,o,{upsert:true})}async updateMany(e,o,n){return await this.requireCollection().updateMany(e,o,n)}async upsertMany(e,o){return await this.requireCollection().updateMany(e,o,{upsert:true})}async deleteOne(e){return await this.requireCollection().deleteOne(e)}async deleteMany(e){return await this.requireCollection().deleteMany(e)}aggregate(e,o){return this.requireCollection().aggregate(e,o)}bulkWrite(e){return this.requireCollection().bulkWrite(e)}getDatabase(){return this.requireClient().db()}rawCollection(){return this.requireCollection()}async renameFrom(e,o){let n=this.getDatabase();if(!this.collection||!n)throw new Error(`Store ${this.name} is not provisioned`);if((await n.listCollections({name:e}).toArray()).length===0)throw new Error(`Collection ${e} not found`);if((await n.listCollections({name:this.name}).toArray()).length>0)throw new Error(`Collection ${this.name} already exists`);await n.collection(e).rename(this.name,o);}};var gt=z.string.bind(z),yt=z.number.bind(z),wt=z.date.bind(z),bt=z.boolean.bind(z),Ct=z.array.bind(z),Et=z.object.bind(z),St=z.enum.bind(z),a={string:gt,number:yt,date:wt,boolean:bt,array:Ct,object:Et,enum:St,objectId(){return z.instanceof(ObjectId)},userId(){return z.instanceof(ObjectId)},ref(t){return z.instanceof(ObjectId)},union:z.union.bind(z),infer(t){return {}}};var v=new f("_modelenceSessions",{schema:{authToken:a.string(),createdAt:a.date(),expiresAt:a.date(),userId:a.userId().nullable()},indexes:[{key:{authToken:1},unique:true},{key:{expiresAt:1}}]});async function je(t){let e=t?await v.findOne({authToken:t}):null;return e?{authToken:String(e.authToken),expiresAt:new Date(e.expiresAt),userId:e.userId??null}:await Mt()}async function Pe(t,e){await v.updateOne({authToken:t},{$set:{userId:e}});}async function $e(t){await v.updateOne({authToken:t},{$set:{userId:null}});}async function Mt(){let t=randomBytes(32).toString("base64url"),e=Date.now(),o=new Date(e+a$1.days(7));return await v.insertOne({authToken:t,createdAt:new Date(e),expiresAt:o,userId:null}),{authToken:t,expiresAt:o,userId:null}}async function Tt(t){let e=Date.now(),o=new Date(e+a$1.days(7));await v.updateOne({authToken:t.authToken},{$set:{lastActiveDate:new Date(e),expiresAt:o}});}var ke=new m("_system.session",{stores:[v],mutations:{init:async function(t,{session:e,user:o}){return {session:e,user:o,configs:ae()}},heartbeat:async function(t,{session:e}){e&&await Tt(e);}}});async function Ue(t,{user:e}){let o=z.string().email().parse(t.email),n=z.string().min(8,{message:"Password must contain at least 8 characters"}).parse(t.password),i=await g.findOne({"emails.address":o},{collation:{locale:"en",strength:2}});if(i){let c=i.emails?.find(u=>u.address===o);throw new Error(`User with email already exists: ${c?.address}`)}let r=await Dt.hash(n,10);return (await g.insertOne({handle:o,emails:[{address:o,verified:false}],createdAt:new Date,authMethods:{password:{hash:r}}})).insertedId}async function Je(t,{user:e,session:o}){if(!o)throw new Error("Session is not initialized");let n=z.string().email().parse(t.email),i=z.string().parse(t.password),r=await g.findOne({"emails.address":n},{collation:{locale:"en",strength:2}}),s=r?.authMethods?.password?.hash;if(!r||!s||!await Dt.compare(i,s))throw ze();return await Pe(o.authToken,r._id),{user:{id:r._id,handle:r.handle}}}async function qe(t,{user:e,session:o}){if(!o)throw new Error("Session is not initialized");await $e(o.authToken);}function ze(){return new Error("Incorrect email/password combination")}var g=new f("_modelenceUsers",{schema:{handle:a.string(),emails:a.array(a.object({address:a.string(),verified:a.boolean()})).optional(),createdAt:a.date(),authMethods:a.object({password:a.object({hash:a.string()}).optional(),google:a.object({id:a.string()}).optional()})},indexes:[{key:{handle:1},unique:true,collation:{locale:"en",strength:2}}]});var Be=new m("_system.user",{stores:[g],mutations:{signupWithPassword:Ue,loginWithPassword:Je,logout:qe}});async function Fe(t){let e=await je(t),o=e.userId?await g.findOne({_id:new ObjectId(e.userId)}):null,n=o?{id:o._id.toString(),handle:o.handle}:null,i=n?Me():k();return {user:n,session:e,roles:i}}function Ke(t){return async(e,o)=>{try{let n=await t({query:e.query,body:e.body,params:e.params,headers:e.headers,cookies:e.cookies,req:e});o.status(n.status||200),n.headers&&Object.entries(n.headers).forEach(([i,r])=>{o.setHeader(i,r);}),o.send(n.data);}catch(n){n instanceof a$3||n instanceof b$1?o.status(n.status).send(n.message):(console.error(`Error in route handler: ${e.path}`),console.error(n),o.status(500).send(String(n)));}}}var y=null;async function We(){if(y)return y;let t=A();if(!t)throw new Error("MongoDB URI is not set");y=new MongoClient(t,{maxPoolSize:20});try{return await y.connect(),await y.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),y}catch(e){throw console.error(e),y=null,e}}function A(){let t=C("_system.mongodbUri");return t?String(t):void 0}function Ve(){return y}function At(t,e){for(let o of e)for(let n of o.routes){let{path:i,handlers:r}=n;Object.entries(r).forEach(([s,c])=>{t[s](i,Ke(c));});}}async function He(t,{combinedModules:e}){let o=G();o.use(G.json()),o.use(G.urlencoded({extended:true})),o.post("/api/_internal/method/:methodName(*)",async(r,s)=>{let{methodName:c}=r.params,u=await _t(r);try{let d=await Ae(c,r.body.args,u);s.json({data:d,typeMap:a$2(d)});}catch(d){if(console.error(`Error in method ${c}:`,d),d instanceof Error&&d?.constructor?.name==="ZodError"&&"errors"in d){let R=d.flatten(),O=Object.entries(R.fieldErrors).map(([J,q])=>`${J}: ${(q??[]).join(", ")}`).join("; "),L=R.formErrors.join("; "),z=[O,L].filter(Boolean).join("; ");s.status(400).send(z);}else s.status(500).send(d instanceof Error?d.message:String(d));}}),At(o,e),await t.init(),t.middlewares&&o.use(t.middlewares()),o.all("*",(r,s)=>t.handler(r,s)),process.on("unhandledRejection",(r,s)=>{console.error("Unhandled Promise Rejection:"),console.error(r instanceof Error?r.stack:r),console.error("Promise:",s);}),process.on("uncaughtException",r=>{console.error("Uncaught Exception:"),console.error(r.stack),console.trace("Full application stack:");});let n=It.createServer(o),i=process.env.PORT||3e3;n.listen(i,()=>{P("Application started",{source:"app"}),console.log(`Application started on port ${i}`);});}async function _t(t){let e=w.string().nullish().transform(r=>r??null).parse(t.body.authToken),o=w.object({screenWidth:w.number(),screenHeight:w.number(),windowWidth:w.number(),windowHeight:w.number(),pixelRatio:w.number(),orientation:w.string().nullable()}).parse(t.body.clientInfo),n={ip:t.ip||t.socket.remoteAddress,userAgent:t.get("user-agent"),acceptLanguage:t.get("accept-language"),referrer:t.get("referrer")};if(!!A()){let{session:r,user:s,roles:c}=await Fe(e);return {clientInfo:o,connectionInfo:n,session:r,user:s,roles:c}}return {clientInfo:o,connectionInfo:n,session:null,user:null,roles:k()}}async function Ze({configSchema:t,cronJobsMetadata:e,stores:o}){let n=process.env.MODELENCE_CONTAINER_ID;if(!n)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");try{let i=Object.values(o).map(s=>({name:s.getName(),schema:s.getSchema(),collections:[s.getName()]})),r=await Y("/api/connect","POST",{hostname:jt.hostname(),containerId:n,dataModels:i,configSchema:t,cronJobsMetadata:e});return console.log("Successfully connected to Modelence Cloud"),r}catch(i){throw console.error("Unable to connect to Modelence Cloud:",i),i}}async function Qe(){return await Y("/api/configs","GET")}async function Ge(){return await Y("/api/sync","POST",{containerId:process.env.MODELENCE_CONTAINER_ID})}async function Y(t,e,o){let{MODELENCE_SERVICE_ENDPOINT:n,MODELENCE_SERVICE_TOKEN:i}=process.env;if(!n)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set");let r=await fetch(`${n}${t}`,{method:e,headers:{Authorization:`Bearer ${i}`,...o?{"Content-Type":"application/json"}:{}},body:o?JSON.stringify(o):void 0});if(!r.ok){let s=await r.text();try{let c=JSON.parse(s);throw new Error(`Unable to connect to Modelence Cloud: HTTP status: ${r.status}, ${c?.error}`)}catch{throw new Error(`Unable to connect to Modelence Cloud: HTTP status: ${r.status}, ${s}`)}}return await r.json()}var X=false,Pt=a$1.seconds(10);function Ye(){setInterval(async()=>{if(!X){X=true;try{await Ge();}catch(t){console.error("Error syncing status",t);}try{await $t();}catch(t){console.error("Error syncing config",t);}X=false;}},Pt);}async function $t(){let{configs:t}=await Qe();I(t);}var U=new f("_modelenceMigrations",{schema:{version:a.number(),appliedAt:a.date()},indexes:[{key:{version:1},unique:true}]});async function Xe(t){if(t.length===0)return;let e=t.map(({version:r})=>r),o=await U.fetch({version:{$in:e}}),n=new Set(o.map(({version:r})=>r)),i=t.filter(({version:r})=>!n.has(r));if(i.length!==0){console.log(`Running migrations (${i.length})...`);for(let{version:r,description:s,handler:c}of i)console.log(`Running migration v${r}: ${s}`),await U.insertOne({version:r,appliedAt:new Date}),await c(),console.log(`Migration v${r} complete`);}}var et=new m("_system.migration",{stores:[U]});var kt=a$1.minutes(1),Nt=a$1.seconds(10),M={},ee,_=new f("_modelenceCronJobs",{schema:{alias:a.string(),lastStartDate:a.date().optional(),lock:a.object({containerId:a.string(),acquireDate:a.date()}).optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function ot(t,{description:e="",interval:o,timeout:n=kt,handler:i}){if(M[t])throw new Error(`Duplicate cron job declaration: '${t}' already exists`);if(ee)throw new Error(`Unable to add a cron job - cron jobs have already been initialized: [${t}]`);if(o<a$1.seconds(5))throw new Error(`Cron job interval should not be less than 5 second [${t}]`);if(n>a$1.days(1))throw new Error(`Cron job timeout should not be longer than 1 day [${t}]`);M[t]={alias:t,params:{description:e,interval:o,timeout:n},handler:i,state:{isRunning:false}};}async function nt(){if(ee)throw new Error("Cron jobs already started");let t=Object.keys(M);if(t.length>0){let e={alias:{$in:t}},o=await _.findOne({...e,"lock.containerId":{$exists:true}});await _.upsertMany(e,{$set:{lock:{containerId:process.env.MODELENCE_CONTAINER_ID||"unknown",acquireDate:new Date}}}),o&&await Ut(Nt);let n=await _.fetch(e),i=Date.now();n.forEach(r=>{let s=M[r.alias];s&&(s.state.scheduledRunTs=r.lastStartDate?r.lastStartDate.getTime()+s.params.interval:i);}),Object.values(M).forEach(r=>{r.state.scheduledRunTs||(r.state.scheduledRunTs=i);}),ee=setInterval(Lt,a$1.seconds(1));}}function Ut(t){return new Promise(e=>setTimeout(e,t))}async function Lt(){let t=Date.now();Object.values(M).forEach(async e=>{let{params:o,state:n}=e;if(n.isRunning){n.startTs&&n.startTs+o.timeout<t&&(n.isRunning=false);return}n.scheduledRunTs&&n.scheduledRunTs<=t&&await zt(e);});}async function zt(t){let{alias:e,params:o,handler:n,state:i}=t;i.isRunning=true,i.startTs=Date.now();let r=$("cron",`cron:${e}`);n().then(()=>{tt(i,o),r.end("success");}).catch(s=>{tt(i,o),Ee(s),r.end("error"),console.error(`Error in cron job '${e}':`,s);}),await _.updateOne({alias:e},{$set:{lastStartDate:new Date(i.startTs)}});}function tt(t,e){t.scheduledRunTs=t.startTs?t.startTs+e.interval:Date.now(),t.startTs=void 0,t.isRunning=false;}function rt(){return Object.values(M).map(({alias:t,params:e})=>({alias:t,description:e.description,interval:e.interval,timeout:e.timeout}))}var it=new m("_system.cron",{stores:[_]});var oe=class{async init(){this.isDev()&&(console.log("Starting Vite dev server..."),this.viteServer=await createServer({...defineConfig(await Wt()),server:{middlewareMode:true},root:"./src/client"}));}middlewares(){return this.isDev()?this.viteServer?.middlewares??[]:[G.static("./.modelence/build/client")]}handler(e,o){if(this.isDev())try{o.sendFile("index.html",{root:"./src/client"});}catch(n){console.error("Error serving index.html:",n),o.status(500).send("Internal Server Error");}else o.sendFile("index.html",{root:"./.modelence/build/client"});}isDev(){return process.env.NODE_ENV!=="production"}};async function Wt(){let t=process.cwd(),e=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(n=>Ft.existsSync(te.join(t,n))),o=[Bt(),Vt()];if(e){let n=(await import('vite-plugin-eslint')).default;o.push(n({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:t,overrideConfigFile:te.resolve(t,e)}));}return {plugins:o,root:t,build:{outDir:".modelence/build/client",emptyOutDir:true},server:{proxy:{"/api":"http://localhost:4000"},headers:{"Cache-Control":"no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0",Pragma:"no-cache",Expires:"0"},hmr:{port:0}},resolve:{alias:{"@":te.resolve(t,"src")}}}}function Vt(){return {name:"modelence-asset-handler",async transform(t,e){if(/\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/.test(e))return process.env.NODE_ENV==="development",t},async generateBundle(t,e){}}}var st=new oe;async function Ht({modules:t=[],roles:e={},defaultRoles:o={},server:n=st,migrations:i=[]}){at.config(),at.config({path:".modelence.env"});let r=!!process.env.MODELENCE_SERVICE_ENDPOINT,s=process.env.MODELENCE_CRON_ENABLED==="true";oo().then(()=>{}).catch(()=>{});let c=[Be,ke,it,et],u=[...c,...t];Qt(c),Zt(t),xe(e,o);let d=Yt(u);ce(d??{});let j=Gt(u);if(s&&Xt(u),r){let{configs:O,deploymentId:L,appAlias:z,deploymentAlias:J,telemetry:q}=await Ze({configSchema:d,cronJobsMetadata:s?rt():void 0,stores:j});I(O),de({deploymentId:L,appAlias:z,deploymentAlias:J,telemetry:q});}else I(to());let R=A();if(R&&(await We(),eo(j)),s&&await Xe(i),R)for(let O of j)O.createIndexes();r&&(await Ce(),Ye()),s&&nt().catch(console.error),await He(n,{combinedModules:u});}function Zt(t){for(let e of t){for(let[o,n]of Object.entries(e.queries))Z(`${e.name}.${o}`,n);for(let[o,n]of Object.entries(e.mutations))De(`${e.name}.${o}`,n);}}function Qt(t){for(let e of t){for(let[o,n]of Object.entries(e.queries))ve(`${e.name}.${o}`,n);for(let[o,n]of Object.entries(e.mutations))Re(`${e.name}.${o}`,n);}}function Gt(t){return t.flatMap(e=>e.stores)}function Yt(t){let e={};for(let o of t)for(let[n,i]of Object.entries(o.configSchema)){let r=`${o.name}.${n}`;if(r in e)throw new Error(`Duplicate config schema key: ${r} (${o.name})`);e[r]=i;}return e}function Xt(t){for(let e of t)for(let[o,n]of Object.entries(e.cronJobs))ot(`${e.name}.${o}`,n);}function eo(t){let e=Ve();if(!e)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let o of t)o.init(e);}function to(){let t=[];return process.env.MONGODB_URI&&t.push({key:"_system.mongodbUri",type:"string",value:process.env.MONGODB_URI}),t}async function oo(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let e=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",o=await import('./package-4OSN27PP.js');await fetch(`${e}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({version:o.default.version})});}}
|
|
3
3
|
export{m as Module,f as Store,Z as createQuery,g as dbUsers,C as getConfig,a as schema,Ht as startApp};//# sourceMappingURL=server.js.map
|
|
4
4
|
//# sourceMappingURL=server.js.map
|