modelence 0.4.14 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +42 -55
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/package-TTREMRUZ.js +3 -0
- package/dist/package-TTREMRUZ.js.map +1 -0
- package/dist/server.d.ts +3 -3
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/package-ZIDFFST7.js +0 -3
- package/dist/package-ZIDFFST7.js.map +0 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { a as ConfigKey } from './types-RXrmChkk.js';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
4
3
|
|
|
5
4
|
declare function getConfig(key: ConfigKey): string | number | boolean;
|
|
6
5
|
|
|
@@ -18,84 +17,72 @@ declare function renderApp({ loadingElement, routesElement, favicon, errorHandle
|
|
|
18
17
|
* Client-side React hooks for data fetching and mutations
|
|
19
18
|
*/
|
|
20
19
|
type Args = Record<string, unknown>;
|
|
21
|
-
type MethodResult<T> = {
|
|
22
|
-
isFetching: boolean;
|
|
23
|
-
error: Error | null;
|
|
24
|
-
data: T | null;
|
|
25
|
-
};
|
|
26
|
-
type PlaceholderData<T> = T | ((prev: T | null) => T);
|
|
27
|
-
type QueryOptions<T> = {
|
|
28
|
-
enabled?: boolean;
|
|
29
|
-
placeholderData?: PlaceholderData<T>;
|
|
30
|
-
};
|
|
31
20
|
declare function callMethod<T = unknown>(methodName: string, args?: Args): Promise<T>;
|
|
32
21
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* This hook automatically executes the query on mount and provides a refetch capability.
|
|
36
|
-
* Similar to React Query's useQuery hook.
|
|
22
|
+
* Creates query options for use with TanStack Query's useQuery hook.
|
|
37
23
|
*
|
|
38
24
|
* @typeParam T - The expected return type of the query
|
|
39
25
|
* @param methodName - The name of the method to query
|
|
40
26
|
* @param args - Optional arguments to pass to the method
|
|
41
|
-
* @
|
|
42
|
-
* @param options.enabled - Boolean indicating if the query should be enabled
|
|
43
|
-
* @returns {Object} An object containing the query state and a refetch function:
|
|
44
|
-
* - `data` - The data returned by the query, or null if not yet loaded
|
|
45
|
-
* - `isFetching` - Boolean indicating if the query is in progress
|
|
46
|
-
* - `error` - Any error that occurred during the query, or null
|
|
47
|
-
* - `refetch` - Function to manually trigger a refetch with optional new arguments
|
|
27
|
+
* @returns Query options object for TanStack Query's useQuery
|
|
48
28
|
*
|
|
49
29
|
* @example
|
|
50
30
|
* ```tsx
|
|
31
|
+
* import { useQuery } from '@tanstack/react-query';
|
|
32
|
+
* import { modelenceQuery } from 'modelence/client';
|
|
33
|
+
*
|
|
51
34
|
* function MyComponent() {
|
|
52
|
-
* //
|
|
53
|
-
* const { data
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* }
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
35
|
+
* // Basic usage
|
|
36
|
+
* const { data } = useQuery(modelenceQuery('todo.getAll'));
|
|
37
|
+
*
|
|
38
|
+
* // With additional options
|
|
39
|
+
* const { data: todo } = useQuery({
|
|
40
|
+
* ...modelenceQuery('todo.getById', { id: '123' }),
|
|
41
|
+
* enabled: !!id,
|
|
42
|
+
* staleTime: 5 * 60 * 1000,
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
60
45
|
* return <div>{data?.name}</div>;
|
|
61
46
|
* }
|
|
62
47
|
* ```
|
|
63
48
|
*/
|
|
64
|
-
declare function
|
|
65
|
-
|
|
66
|
-
|
|
49
|
+
declare function modelenceQuery<T = unknown>(methodName: string, args?: Args): {
|
|
50
|
+
queryKey: (string | Args)[];
|
|
51
|
+
queryFn: () => Promise<T>;
|
|
67
52
|
};
|
|
68
53
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* This hook provides functions to trigger the mutation manually and handles loading/error states.
|
|
72
|
-
* Similar to React Query's useMutation hook.
|
|
54
|
+
* Creates mutation options for use with TanStack Query's useMutation hook.
|
|
73
55
|
*
|
|
74
56
|
* @typeParam T - The expected return type of the mutation
|
|
75
57
|
* @param methodName - The name of the method to mutate
|
|
76
|
-
* @param
|
|
77
|
-
* @returns
|
|
78
|
-
* - `data` - The data returned by the last successful mutation, or null
|
|
79
|
-
* - `isFetching` - Boolean indicating if the mutation is in progress
|
|
80
|
-
* - `error` - Any error that occurred during the last mutation, or null
|
|
81
|
-
* - `mutate` - Function to trigger the mutation with optional arguments
|
|
82
|
-
* - `mutateAsync` - Promise-returning version of mutate, useful for awaiting the result
|
|
58
|
+
* @param defaultArgs - Optional default arguments to merge with mutation variables
|
|
59
|
+
* @returns Mutation options object for TanStack Query's useMutation
|
|
83
60
|
*
|
|
84
61
|
* @example
|
|
85
62
|
* ```tsx
|
|
86
|
-
*
|
|
63
|
+
* import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
64
|
+
* import { modelenceMutation } from 'modelence/client';
|
|
65
|
+
*
|
|
66
|
+
* function MyComponent() {
|
|
67
|
+
* const queryClient = useQueryClient();
|
|
87
68
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
69
|
+
* // Basic usage
|
|
70
|
+
* const { mutate } = useMutation(modelenceMutation('todos.create'));
|
|
71
|
+
*
|
|
72
|
+
* // With additional options
|
|
73
|
+
* const { mutate: updateTodo } = useMutation({
|
|
74
|
+
* ...modelenceMutation('todos.update'),
|
|
75
|
+
* onSuccess: () => {
|
|
76
|
+
* queryClient.invalidateQueries({ queryKey: ['todos.getAll'] });
|
|
77
|
+
* },
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* return <button onClick={() => mutate({ title: 'New Todo' })}>Create</button>;
|
|
81
|
+
* }
|
|
90
82
|
* ```
|
|
91
83
|
*/
|
|
92
|
-
declare function
|
|
93
|
-
|
|
94
|
-
error: Error | null;
|
|
95
|
-
isFetching: boolean;
|
|
96
|
-
isPending: boolean;
|
|
97
|
-
mutate: _tanstack_react_query.UseMutateFunction<T, Error, Args | undefined, unknown>;
|
|
98
|
-
mutateAsync: _tanstack_react_query.UseMutateAsyncFunction<T, Error, Args | undefined, unknown>;
|
|
84
|
+
declare function modelenceMutation<T = unknown>(methodName: string, defaultArgs?: Args): {
|
|
85
|
+
mutationFn: (variables?: Args) => Promise<T>;
|
|
99
86
|
};
|
|
100
87
|
|
|
101
88
|
type User$1 = {
|
|
@@ -122,4 +109,4 @@ declare function logout(): Promise<void>;
|
|
|
122
109
|
|
|
123
110
|
declare const AppProvider: any;
|
|
124
111
|
|
|
125
|
-
export { AppProvider, callMethod, getConfig, loginWithPassword, logout,
|
|
112
|
+
export { AppProvider, callMethod, getConfig, loginWithPassword, logout, modelenceMutation, modelenceQuery, renderApp, signupWithPassword, useSession };
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {b
|
|
1
|
+
import {b}from'./chunk-DN5SVAO2.js';import {a as a$1}from'./chunk-R7MPLJMA.js';import H,{useState,useEffect}from'react';import {create}from'zustand';import {z as z$1}from'zod';import {QueryClient,QueryClientProvider}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 w=(e,r)=>{throw new Error(`Error calling method '${r}': ${e.toString()}`)};function h(e){w=e;}function y(e,r){return w(e,r)}async function t(e,r={}){try{return await U(`/api/_internal/method/${e}`,r)}catch(o){throw y(o,e),o}}async function U(e,r){let o=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(!o.ok){let s=await o.text();throw new Error(s)}let n=await o.text(),i=n?JSON.parse(n):void 0;if(!i)throw new Error("Invalid response from server");return b(i.data,i.typeMap)}function k(e,r={}){return {queryKey:[e,r],queryFn:()=>t(e,r)}}function L(e,r={}){return {mutationFn:(o={})=>t(e,{...r,...o})}}var a={};function M(e){if(!(e in a))throw new Error(`Unknown config: ${e}`);return a[e]?.value}function S(e){a=e;}var l=create(e=>({user:null,setUser:r=>e({user:r})})),E=false,I=a$1.seconds(30);async function x(){if(E)return;E=true;let{configs:e,session:r,user:o}=await t("_system.session.init");S(e),m(r);let n=o?Object.freeze(z$1.object({id:z$1.string(),handle:z$1.string()}).parse(o)):null;l.getState().setUser(n),await C();}async function C(){await t("_system.session.heartbeat"),setTimeout(C,I);}function d(e){l.getState().setUser(e);}function N(){return {user:l(r=>r.user)}}var P=false,J=new QueryClient({defaultOptions:{queries:{refetchOnWindowFocus:false}}});function u({children:e,loadingElement:r}){let[o,n]=useState(true);return useEffect(()=>{async function i(){P||(P=true,await x(),n(false));}i();},[]),o?r??jsx("div",{children:"Loading..."}):jsx(QueryClientProvider,{client:J,children:e})}function z({loadingElement:e,routesElement:r,favicon:o,errorHandler:n}){if(n&&h(n),window.addEventListener("unload",()=>{}),j.createRoot(document.getElementById("root")).render(jsx(H.StrictMode,{children:jsx(R,{loadingElement:e,children:r})})),o){let i=document.querySelector("link[rel~='icon']");if(i)i.href=o;else {let s=document.createElement("link");s.rel="icon",s.href=o,document.head.appendChild(s);}}}async function K({email:e,password:r}){await t("_system.user.signupWithPassword",{email:e,password:r}),await T({email:e,password:r});}async function T({email:e,password:r}){let{user:o}=await t("_system.user.loginWithPassword",{email:e,password:r});return d(o),o}async function $(){await t("_system.user.logout"),d(null);}var R="useClient"in H?H.useClient(u):u;export{R as AppProvider,t as callMethod,M as getConfig,T as loginWithPassword,$ as logout,L as modelenceMutation,k as modelenceQuery,z as renderApp,K as signupWithPassword,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 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
|
+
{"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","modelenceQuery","modelenceMutation","defaultArgs","variables","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 { getLocalStorageSession } from './localStorage';\nimport { handleError } from './errorHandler';\nimport { reviveResponseTypes } from '../methods/serialize';\n\ntype Args = Record<string, unknown>;\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 * Creates query options for use with TanStack 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 * @returns Query options object for TanStack Query's useQuery\n * \n * @example\n * ```tsx\n * import { useQuery } from '@tanstack/react-query';\n * import { modelenceQuery } from 'modelence/client';\n * \n * function MyComponent() {\n * // Basic usage\n * const { data } = useQuery(modelenceQuery('todo.getAll'));\n * \n * // With additional options\n * const { data: todo } = useQuery({\n * ...modelenceQuery('todo.getById', { id: '123' }),\n * enabled: !!id,\n * staleTime: 5 * 60 * 1000,\n * });\n * \n * return <div>{data?.name}</div>;\n * }\n * ```\n */\nexport function modelenceQuery<T = unknown>(\n methodName: string, \n args: Args = {}\n) {\n return {\n queryKey: [methodName, args],\n queryFn: () => callMethod<T>(methodName, args),\n };\n}\n\n/**\n * Creates mutation options for use with TanStack 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 defaultArgs - Optional default arguments to merge with mutation variables\n * @returns Mutation options object for TanStack Query's useMutation\n * \n * @example\n * ```tsx\n * import { useMutation, useQueryClient } from '@tanstack/react-query';\n * import { modelenceMutation } from 'modelence/client';\n * \n * function MyComponent() {\n * const queryClient = useQueryClient();\n * \n * // Basic usage\n * const { mutate } = useMutation(modelenceMutation('todos.create'));\n * \n * // With additional options\n * const { mutate: updateTodo } = useMutation({\n * ...modelenceMutation('todos.update'),\n * onSuccess: () => {\n * queryClient.invalidateQueries({ queryKey: ['todos.getAll'] });\n * },\n * });\n * \n * return <button onClick={() => mutate({ title: 'New Todo' })}>Create</button>;\n * }\n * ```\n */\nexport function modelenceMutation<T = unknown>(\n methodName: string, \n defaultArgs: Args = {}\n) {\n return {\n mutationFn: (variables: Args = {}) => callMethod<T>(methodName, { ...defaultArgs, ...variables }),\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 { modelenceQuery, modelenceMutation, callMethod } from './client/method';\nexport { useSession } from './client/session';\nexport { signupWithPassword, loginWithPassword, logout } from './auth/client';\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var s="module",i="modelence",n="0.5.0",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-TTREMRUZ.js.map
|
|
3
|
+
//# sourceMappingURL=package-TTREMRUZ.js.map
|
|
@@ -0,0 +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,OAAA,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-TTREMRUZ.js","sourcesContent":["{\n \"type\": \"module\",\n \"name\": \"modelence\",\n \"version\": \"0.5.0\",\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.d.ts
CHANGED
|
@@ -39,8 +39,8 @@ declare const schema: {
|
|
|
39
39
|
readonly boolean: (params?: z.RawCreateParams & {
|
|
40
40
|
coerce?: boolean;
|
|
41
41
|
}) => z.ZodBoolean;
|
|
42
|
-
readonly array: <
|
|
43
|
-
readonly object: <
|
|
42
|
+
readonly array: <El extends z.ZodTypeAny>(schema: El, params?: z.RawCreateParams) => z.ZodArray<El>;
|
|
43
|
+
readonly object: <Shape extends z.ZodRawShape>(shape: Shape, params?: z.RawCreateParams) => z.ZodObject<Shape, "strip", z.ZodTypeAny, z.objectOutputType<Shape, z.ZodTypeAny, "strip">, z.objectInputType<Shape, z.ZodTypeAny, "strip">>;
|
|
44
44
|
readonly enum: {
|
|
45
45
|
<U extends string, T extends Readonly<[U, ...U[]]>>(values: T, params?: z.RawCreateParams): z.ZodEnum<z.Writeable<T>>;
|
|
46
46
|
<U extends string, T extends [U, ...U[]]>(values: T, params?: z.RawCreateParams): z.ZodEnum<T>;
|
|
@@ -48,7 +48,7 @@ declare const schema: {
|
|
|
48
48
|
readonly objectId: () => z.ZodType<ObjectId$1>;
|
|
49
49
|
readonly userId: () => z.ZodType<ObjectId$1>;
|
|
50
50
|
readonly ref: (collection: string | Store<any, any>) => z.ZodType<ObjectId$1>;
|
|
51
|
-
readonly union: <
|
|
51
|
+
readonly union: <Options extends Readonly<[z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]>>(types: Options, params?: z.RawCreateParams) => z.ZodUnion<Options>;
|
|
52
52
|
readonly infer: <T extends SchemaTypeDefinition>(schema: T) => InferDocumentType<T>;
|
|
53
53
|
};
|
|
54
54
|
declare namespace schema {
|
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 ct from'dotenv';import Ot from'http';import G from'express';import w,{z}from'zod';import mt 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 _t from'os';import $t from'bcrypt';import {createServer,defineConfig}from'vite';import Ft from'@vitejs/plugin-react';import te from'path';import Kt from'fs';function lt(){return typeof window!="object"}function b(){if(!lt())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 ue(t){E=Object.assign({},E,t);}function de(){return E?.deploymentId}function pe(){return E?.appAlias}function me(){return E?.deploymentAlias}function fe(){return E?.telemetry?.serviceName}function x(){return !!E?.telemetry?.isEnabled}function P(t,e){x()&&K().info(t,e);}function he(t,e){x()&&K().error(t,e);}var g={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(),g.stdout),o.call(T.stdout,i,...r)},T.stderr.write=function(i,...r){return ge(i.toString(),g.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 pt(){let t=g.stdout.slice(0,-1);g.stdout=[g.stdout[g.stdout.length-1]];let e=g.stderr.slice(0,-1);g.stderr=[g.stderr[g.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(()=>{pt(),we();},1e3);}var be=false,S=null,V=null,Ce=async()=>{if(be)throw new Error('Metrics are already initialized, duplicate "initMetrics" call received');be=true,x()&&await ht();};async function ht(){let t=C("_system.elastic.apmEndpoint"),e=C("_system.elastic.cloudId"),o=C("_system.elastic.apiKey"),n=pe()??"unknown",i=me()??"unknown",r=de()??"unknown",s=fe();S=mt.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:S,level:"debug",clientOpts:{cloud:{id:e},auth:{apiKey:o},requestTimeout:1e4,tls:{rejectUnauthorized:false}},bufferLimit:1e3,silent:false});c.on("error",d=>{console.error("Elasticsearch Transport Error:",d);}),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(!x())return {end:()=>{}};if(!S)throw new Error("startTransaction: Elastic APM is not initialized");let n=S.startTransaction(e,t);return o&&S.setCustomContext(o),n}function Ee(t){if(!x()){console.error(t);return}if(!S)throw new Error("captureError: Elastic APM is not initialized");S.captureError(t);}function K(){if(!V)throw new Error("Logger is not initialized");return V}var xe=new Map,D={authenticated:null,unauthenticated:null};function Se(t,e){D.authenticated=e.authenticated,D.unauthenticated=e.unauthenticated;for(let[o,n]of Object.entries(t))xe.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=>!gt(t,n));if(o)throw new Error(`Access denied - missing permission: '${o}'`)}function gt(t,e){for(let o of t){let n=xe.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(d){throw s.end("error"),d}return s.end(),c}var f=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 h=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 yt=z.string.bind(z),wt=z.number.bind(z),bt=z.date.bind(z),Ct=z.boolean.bind(z),Et=z.array.bind(z),xt=z.object.bind(z),St=z.enum.bind(z),a={string:yt,number:wt,date:bt,boolean:Ct,array:Et,object:xt,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 h("_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 Tt()}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 Tt(){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 Dt(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 f("_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 Dt(e);}}});var p=new h("_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}}]});async function Ne(t){let e=await je(t),o=e.userId?await p.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 Ue(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 Le(){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 qe(){return y}function It(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,Ue(c));});}}async function ze(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,d=await At(r);try{let u=await Ae(c,r.body.args,d);s.json({data:u,typeMap:a$2(u)});}catch(u){if(console.error(`Error in method ${c}:`,u),u instanceof Error&&u?.constructor?.name==="ZodError"&&"errors"in u){let R=u.flatten(),O=Object.entries(R.fieldErrors).map(([z,J])=>`${z}: ${(J??[]).join(", ")}`).join("; "),L=R.formErrors.join("; "),q=[O,L].filter(Boolean).join("; ");s.status(400).send(q);}else s.status(500).send(u instanceof Error?u.message:String(u));}}),It(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=Ot.createServer(o),i=process.env.PORT||3e3;n.listen(i,()=>{P("Application started",{source:"app"}),console.log(`Application started on port ${i}`);});}async function At(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 Ne(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 Je({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:_t.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 Be(){return await Y("/api/configs","GET")}async function Fe(){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,jt=a$1.seconds(10);function Ke(){setInterval(async()=>{if(!X){X=true;try{await Fe();}catch(t){console.error("Error syncing status",t);}try{await Pt();}catch(t){console.error("Error syncing config",t);}X=false;}},jt);}async function Pt(){let{configs:t}=await Be();I(t);}async function Ve(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 p.findOne({"emails.address":o},{collation:{locale:"en",strength:2}});if(i){let c=i.emails?.find(d=>d.address===o);throw new Error(`User with email already exists: ${c?.address}`)}let r=await $t.hash(n,10);return (await p.insertOne({handle:o,emails:[{address:o,verified:false}],createdAt:new Date,authMethods:{password:{hash:r}}})).insertedId}async function Qe(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 p.findOne({"emails.address":n},{collation:{locale:"en",strength:2}}),s=r?.authMethods?.password?.hash;if(!r||!s||!await $t.compare(i,s))throw Ze();return await Pe(o.authToken,r._id),{user:{id:r._id,handle:r.handle}}}async function Ge(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")}async function Ye(t,{user:e}){if(!e)throw new Error("Not authenticated");let o=await p.requireById(e.id);return {handle:o.handle,emails:o.emails,authMethods:Object.keys(o.authMethods||{})}}var Xe=new f("_system.user",{stores:[p],queries:{getOwnProfile:Ye},mutations:{signupWithPassword:Ve,loginWithPassword:Qe,logout:Ge}});var U=new h("_modelenceMigrations",{schema:{version:a.number(),appliedAt:a.date()},indexes:[{key:{version:1},unique:true}]});async function et(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 tt=new f("_system.migration",{stores:[U]});var Nt=a$1.minutes(1),Ut=a$1.seconds(10),M={},ee,_=new h("_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 nt(t,{description:e="",interval:o,timeout:n=Nt,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 rt(){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 Lt(Ut);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(qt,a$1.seconds(1));}}function Lt(t){return new Promise(e=>setTimeout(e,t))}async function qt(){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(()=>{ot(i,o),r.end("success");}).catch(s=>{ot(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 ot(t,e){t.scheduledRunTs=t.startTs?t.startTs+e.interval:Date.now(),t.startTs=void 0,t.isRunning=false;}function it(){return Object.values(M).map(({alias:t,params:e})=>({alias:t,description:e.description,interval:e.interval,timeout:e.timeout}))}var st=new f("_system.cron",{stores:[_]});var oe=class{async init(){this.isDev()&&(console.log("Starting Vite dev server..."),this.viteServer=await createServer({...defineConfig(await Vt()),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 Vt(){let t=process.cwd(),e=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(n=>Kt.existsSync(te.join(t,n))),o=[Ft(),Ht()];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 Ht(){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 at=new oe;async function Zt({modules:t=[],roles:e={},defaultRoles:o={},server:n=at,migrations:i=[]}){ct.config(),ct.config({path:".modelence.env"});let r=!!process.env.MODELENCE_SERVICE_ENDPOINT,s=process.env.MODELENCE_CRON_ENABLED==="true";no().then(()=>{}).catch(()=>{});let c=[Xe,ke,st,tt],d=[...c,...t];Gt(c),Qt(t),Se(e,o);let u=Xt(d);ce(u??{});let j=Yt(d);if(s&&eo(d),r){let{configs:O,deploymentId:L,appAlias:q,deploymentAlias:z,telemetry:J}=await Je({configSchema:u,cronJobsMetadata:s?it():void 0,stores:j});I(O),ue({deploymentId:L,appAlias:q,deploymentAlias:z,telemetry:J});}else I(oo());let R=A();if(R&&(await Le(),to(j)),s&&await et(i),R)for(let O of j)O.createIndexes();r&&(await Ce(),Ke()),s&&rt().catch(console.error),await ze(n,{combinedModules:d});}function Qt(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 Gt(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 Yt(t){return t.flatMap(e=>e.stores)}function Xt(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 eo(t){for(let e of t)for(let[o,n]of Object.entries(e.cronJobs))nt(`${e.name}.${o}`,n);}function to(t){let e=qe();if(!e)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let o of t)o.init(e);}function oo(){let t=[];return process.env.MONGODB_URI&&t.push({key:"_system.mongodbUri",type:"string",value:process.env.MONGODB_URI}),t}async function no(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let e=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",o=await import('./package-ZIDFFST7.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 pt(){let t=g.stdout.slice(0,-1);g.stdout=[g.stdout[g.stdout.length-1]];let e=g.stderr.slice(0,-1);g.stderr=[g.stderr[g.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(()=>{pt(),we();},1e3);}var be=false,S=null,V=null,Ce=async()=>{if(be)throw new Error('Metrics are already initialized, duplicate "initMetrics" call received');be=true,x()&&await ht();};async function ht(){let t=C("_system.elastic.apmEndpoint"),e=C("_system.elastic.cloudId"),o=C("_system.elastic.apiKey"),n=pe()??"unknown",i=me()??"unknown",r=de()??"unknown",s=fe();S=mt.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:S,level:"debug",clientOpts:{cloud:{id:e},auth:{apiKey:o},requestTimeout:1e4,tls:{rejectUnauthorized:false}},bufferLimit:1e3,silent:false});c.on("error",d=>{console.error("Elasticsearch Transport Error:",d);}),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(!x())return {end:()=>{}};if(!S)throw new Error("startTransaction: Elastic APM is not initialized");let n=S.startTransaction(e,t);return o&&S.setCustomContext(o),n}function Ee(t){if(!x()){console.error(t);return}if(!S)throw new Error("captureError: Elastic APM is not initialized");S.captureError(t);}function K(){if(!V)throw new Error("Logger is not initialized");return V}var xe=new Map,D={authenticated:null,unauthenticated:null};function Se(t,e){D.authenticated=e.authenticated,D.unauthenticated=e.unauthenticated;for(let[o,n]of Object.entries(t))xe.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=>!gt(t,n));if(o)throw new Error(`Access denied - missing permission: '${o}'`)}function gt(t,e){for(let o of t){let n=xe.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(d){throw s.end("error"),d}return s.end(),c}var f=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 h=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 yt=z.string.bind(z),wt=z.number.bind(z),bt=z.date.bind(z),Ct=z.boolean.bind(z),Et=z.array.bind(z),xt=z.object.bind(z),St=z.enum.bind(z),a={string:yt,number:wt,date:bt,boolean:Ct,array:Et,object:xt,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 h("_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 Tt()}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 Tt(){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 Dt(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 f("_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 Dt(e);}}});var p=new h("_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}}]});async function Ne(t){let e=await je(t),o=e.userId?await p.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 Ue(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 Le(){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 qe(){return y}function It(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,Ue(c));});}}async function ze(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,d=await At(r);try{let u=await Ae(c,r.body.args,d);s.json({data:u,typeMap:a$2(u)});}catch(u){if(console.error(`Error in method ${c}:`,u),u instanceof Error&&u?.constructor?.name==="ZodError"&&"errors"in u){let R=u.flatten(),O=Object.entries(R.fieldErrors).map(([z,J])=>`${z}: ${(J??[]).join(", ")}`).join("; "),L=R.formErrors.join("; "),q=[O,L].filter(Boolean).join("; ");s.status(400).send(q);}else s.status(500).send(u instanceof Error?u.message:String(u));}}),It(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=Ot.createServer(o),i=process.env.PORT||3e3;n.listen(i,()=>{P("Application started",{source:"app"}),console.log(`Application started on port ${i}`);});}async function At(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 Ne(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 Je({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:_t.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 Be(){return await Y("/api/configs","GET")}async function Fe(){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,jt=a$1.seconds(10);function Ke(){setInterval(async()=>{if(!X){X=true;try{await Fe();}catch(t){console.error("Error syncing status",t);}try{await Pt();}catch(t){console.error("Error syncing config",t);}X=false;}},jt);}async function Pt(){let{configs:t}=await Be();I(t);}async function Ve(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 p.findOne({"emails.address":o},{collation:{locale:"en",strength:2}});if(i){let c=i.emails?.find(d=>d.address===o);throw new Error(`User with email already exists: ${c?.address}`)}let r=await $t.hash(n,10);return (await p.insertOne({handle:o,emails:[{address:o,verified:false}],createdAt:new Date,authMethods:{password:{hash:r}}})).insertedId}async function Qe(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 p.findOne({"emails.address":n},{collation:{locale:"en",strength:2}}),s=r?.authMethods?.password?.hash;if(!r||!s||!await $t.compare(i,s))throw Ze();return await Pe(o.authToken,r._id),{user:{id:r._id,handle:r.handle}}}async function Ge(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")}async function Ye(t,{user:e}){if(!e)throw new Error("Not authenticated");let o=await p.requireById(e.id);return {handle:o.handle,emails:o.emails,authMethods:Object.keys(o.authMethods||{})}}var Xe=new f("_system.user",{stores:[p],queries:{getOwnProfile:Ye},mutations:{signupWithPassword:Ve,loginWithPassword:Qe,logout:Ge}});var U=new h("_modelenceMigrations",{schema:{version:a.number(),appliedAt:a.date()},indexes:[{key:{version:1},unique:true}]});async function et(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 tt=new f("_system.migration",{stores:[U]});var Nt=a$1.minutes(1),Ut=a$1.seconds(10),M={},ee,_=new h("_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 nt(t,{description:e="",interval:o,timeout:n=Nt,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 rt(){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 Lt(Ut);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(qt,a$1.seconds(1));}}function Lt(t){return new Promise(e=>setTimeout(e,t))}async function qt(){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(()=>{ot(i,o),r.end("success");}).catch(s=>{ot(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 ot(t,e){t.scheduledRunTs=t.startTs?t.startTs+e.interval:Date.now(),t.startTs=void 0,t.isRunning=false;}function it(){return Object.values(M).map(({alias:t,params:e})=>({alias:t,description:e.description,interval:e.interval,timeout:e.timeout}))}var st=new f("_system.cron",{stores:[_]});var oe=class{async init(){this.isDev()&&(console.log("Starting Vite dev server..."),this.viteServer=await createServer({...defineConfig(await Vt()),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 Vt(){let t=process.cwd(),e=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(n=>Kt.existsSync(te.join(t,n))),o=[Ft(),Ht()];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 Ht(){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 at=new oe;async function Zt({modules:t=[],roles:e={},defaultRoles:o={},server:n=at,migrations:i=[]}){ct.config(),ct.config({path:".modelence.env"});let r=!!process.env.MODELENCE_SERVICE_ENDPOINT,s=process.env.MODELENCE_CRON_ENABLED==="true";no().then(()=>{}).catch(()=>{});let c=[Xe,ke,st,tt],d=[...c,...t];Gt(c),Qt(t),Se(e,o);let u=Xt(d);ce(u??{});let j=Yt(d);if(s&&eo(d),r){let{configs:O,deploymentId:L,appAlias:q,deploymentAlias:z,telemetry:J}=await Je({configSchema:u,cronJobsMetadata:s?it():void 0,stores:j});I(O),ue({deploymentId:L,appAlias:q,deploymentAlias:z,telemetry:J});}else I(oo());let R=A();if(R&&(await Le(),to(j)),s&&await et(i),R)for(let O of j)O.createIndexes();r&&(await Ce(),Ke()),s&&rt().catch(console.error),await ze(n,{combinedModules:d});}function Qt(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 Gt(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 Yt(t){return t.flatMap(e=>e.stores)}function Xt(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 eo(t){for(let e of t)for(let[o,n]of Object.entries(e.cronJobs))nt(`${e.name}.${o}`,n);}function to(t){let e=qe();if(!e)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let o of t)o.init(e);}function oo(){let t=[];return process.env.MONGODB_URI&&t.push({key:"_system.mongodbUri",type:"string",value:process.env.MONGODB_URI}),t}async function no(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let e=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",o=await import('./package-TTREMRUZ.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{f as Module,h as Store,Z as createQuery,p as dbUsers,C as getConfig,a as schema,Zt as startApp};//# sourceMappingURL=server.js.map
|
|
4
4
|
//# sourceMappingURL=server.js.map
|
package/package.json
CHANGED
package/dist/package-ZIDFFST7.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
var s="module",i="modelence",n="0.4.14",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-ZIDFFST7.js.map
|
|
3
|
-
//# sourceMappingURL=package-ZIDFFST7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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-ZIDFFST7.js","sourcesContent":["{\n \"type\": \"module\",\n \"name\": \"modelence\",\n \"version\": \"0.4.14\",\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"]}
|