modelence 0.18.0-dev.0 → 0.18.0-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-7E2S5HNK.js → chunk-4GRKA5XD.js} +3 -3
- package/dist/{chunk-7E2S5HNK.js.map → chunk-4GRKA5XD.js.map} +1 -1
- package/dist/chunk-EPSYTDTF.js +19 -0
- package/dist/chunk-EPSYTDTF.js.map +1 -0
- package/dist/collectCss-4V7I3QV3.js +2 -0
- package/dist/collectCss-4V7I3QV3.js.map +1 -0
- package/dist/{package-J4VDCT4N.js → package-LHHQ7BNW.js} +2 -2
- package/dist/{package-J4VDCT4N.js.map → package-LHHQ7BNW.js.map} +1 -1
- package/dist/render-NUGKBTTZ.js +2 -0
- package/dist/render-NUGKBTTZ.js.map +1 -0
- package/dist/server-XAIFPVGX.js +2 -0
- package/dist/{server-UZKGL5C6.js.map → server-XAIFPVGX.js.map} +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-S3BSPKUV.js +0 -19
- package/dist/chunk-S3BSPKUV.js.map +0 -1
- package/dist/render-LCYTTXNW.js +0 -2
- package/dist/render-LCYTTXNW.js.map +0 -1
- package/dist/server-UZKGL5C6.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import a from'path';import u from'fs';var l=/\.(css|scss|sass|less|styl|stylus|pcss|postcss)(\?|$)/,p=Object.freeze({hrefs:[],source:"dev"});function y(s,e){let t=s.moduleGraph.getModuleById(d(s,e));if(!t)return p;let n=new Set,o=[],i=new Set,c=r=>{if(!n.has(r)){n.add(r),r.url&&l.test(r.url)&&!i.has(r.url)&&(i.add(r.url),o.push(r.url));for(let f of r.importedModules)c(f);for(let f of r.ssrImportedModules)c(f);}};return c(t),{hrefs:o,source:"dev"}}function d(s,e){let t=s.config.root;return a.join(t,e).replace(/\\/g,"/")}function A(s){let e=a.resolve(process.cwd(),s,".vite","ssr-manifest.json");if(!u.existsSync(e))return {hrefs:[],source:"prod"};let t;try{t=JSON.parse(u.readFileSync(e,"utf-8"));}catch(o){return console.warn("Modelence SSR: failed to parse ssr-manifest.json",o),{hrefs:[],source:"prod"}}let n=new Set;for(let o of Object.values(t))if(Array.isArray(o))for(let i of o)typeof i=="string"&&l.test(i)&&n.add(i);return {hrefs:Array.from(n),source:"prod"}}function v(s){return s.hrefs.length===0?"":s.hrefs.map(e=>`<link rel="stylesheet" href="${h(e)}">`).join("")}function C(s){return s.hrefs.map(e=>`<${e}>; rel=preload; as=style`)}function h(s){return s.replace(/&/g,"&").replace(/"/g,""")}export{C as buildEarlyHintsLink,y as collectDevCssAssets,A as loadProdCssAssets,v as renderStylesheetLinks};//# sourceMappingURL=collectCss-4V7I3QV3.js.map
|
|
2
|
+
//# sourceMappingURL=collectCss-4V7I3QV3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ssr/collectCss.ts"],"names":["CSS_EXTENSION_REGEX","EMPTY_ASSETS","collectDevCssAssets","viteServer","entryVirtualPath","ssrModule","resolveEntryId","seen","hrefs","hrefSet","walk","mod","imported","root","path","loadProdCssAssets","clientBuildDir","manifestPath","fs","manifest","error","assets","asset","renderStylesheetLinks","href","escapeAttribute","buildEarlyHintsLink","value"],"mappings":"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","file":"collectCss-4V7I3QV3.js","sourcesContent":["import path from 'path';\nimport fs from 'fs';\nimport type { ViteDevServer, ModuleNode } from 'vite';\n\nconst CSS_EXTENSION_REGEX = /\\.(css|scss|sass|less|styl|stylus|pcss|postcss)(\\?|$)/;\n\nexport type CssAssetSource = 'dev' | 'prod';\n\nexport interface CssAssets {\n /**\n * Public URLs suitable for emitting as <link rel=\"stylesheet\">. In dev these\n * point at Vite's transform endpoint; in prod they point at the built asset.\n */\n hrefs: string[];\n source: CssAssetSource;\n}\n\nconst EMPTY_ASSETS: CssAssets = Object.freeze({ hrefs: [], source: 'dev' }) as CssAssets;\n\n/**\n * Walk the Vite dev module graph from the SSR entry, collecting every CSS\n * module pulled in by the rendered tree. Returns URLs that the browser can\n * request directly so the dev HTML can ship <link rel=\"stylesheet\"> tags\n * before the client JS runs (kills FOUC in dev).\n */\nexport function collectDevCssAssets(\n viteServer: ViteDevServer,\n entryVirtualPath: string\n): CssAssets {\n const ssrModule = viteServer.moduleGraph.getModuleById(\n resolveEntryId(viteServer, entryVirtualPath)\n );\n if (!ssrModule) {\n return EMPTY_ASSETS;\n }\n\n const seen = new Set<ModuleNode>();\n const hrefs: string[] = [];\n const hrefSet = new Set<string>();\n\n const walk = (mod: ModuleNode) => {\n if (seen.has(mod)) {\n return;\n }\n seen.add(mod);\n\n if (mod.url && CSS_EXTENSION_REGEX.test(mod.url) && !hrefSet.has(mod.url)) {\n hrefSet.add(mod.url);\n hrefs.push(mod.url);\n }\n\n for (const imported of mod.importedModules) {\n walk(imported);\n }\n for (const imported of mod.ssrImportedModules) {\n walk(imported);\n }\n };\n\n walk(ssrModule);\n\n return { hrefs, source: 'dev' };\n}\n\nfunction resolveEntryId(viteServer: ViteDevServer, entryVirtualPath: string): string {\n const root = viteServer.config.root;\n // `entryVirtualPath` is rooted at Vite's `root` (e.g. '/index.tsx' under\n // 'src/client'). The module graph keys modules by absolute file id.\n const absolutePath = path.join(root, entryVirtualPath).replace(/\\\\/g, '/');\n return absolutePath;\n}\n\ntype SsrManifest = Record<string, string[]>;\n\n/**\n * Read the production SSR manifest produced by `vite build --ssr`. The manifest\n * maps every JS module id to the CSS/asset URLs the client must load to render\n * its output. We flatten the unique CSS entries — the SSR render only touched a\n * subset of routes per request, but at framework boot we don't yet have a\n * per-request module list, so we emit the full set. This matches the behavior\n * of a non-streaming build.\n */\nexport function loadProdCssAssets(clientBuildDir: string): CssAssets {\n const manifestPath = path.resolve(process.cwd(), clientBuildDir, '.vite', 'ssr-manifest.json');\n\n if (!fs.existsSync(manifestPath)) {\n return { hrefs: [], source: 'prod' };\n }\n\n let manifest: SsrManifest;\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as SsrManifest;\n } catch (error) {\n console.warn('Modelence SSR: failed to parse ssr-manifest.json', error);\n return { hrefs: [], source: 'prod' };\n }\n\n const hrefSet = new Set<string>();\n for (const assets of Object.values(manifest)) {\n if (!Array.isArray(assets)) {\n continue;\n }\n for (const asset of assets) {\n if (typeof asset === 'string' && CSS_EXTENSION_REGEX.test(asset)) {\n hrefSet.add(asset);\n }\n }\n }\n\n return { hrefs: Array.from(hrefSet), source: 'prod' };\n}\n\n/**\n * Render the CSS asset URLs as HTML <link rel=\"stylesheet\"> tags. React 19\n * users who render <link precedence=...> inside components get React Float's\n * dedup + ordering automatically; this helper exists for the framework-level\n * tags injected into the template <head> before the React shell.\n */\nexport function renderStylesheetLinks(assets: CssAssets): string {\n if (assets.hrefs.length === 0) {\n return '';\n }\n return assets.hrefs\n .map((href) => `<link rel=\"stylesheet\" href=\"${escapeAttribute(href)}\">`)\n .join('');\n}\n\n/**\n * Build a Link header value for HTTP 103 Early Hints. The browser starts the\n * stylesheet fetch as soon as it sees this response, before the SSR render\n * has even begun.\n */\nexport function buildEarlyHintsLink(assets: CssAssets): string[] {\n return assets.hrefs.map((href) => `<${href}>; rel=preload; as=style`);\n}\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"');\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{l as author,i as bin,n as bugs,s as default,q as dependencies,d as description,p as devDependencies,g as exports,h as files,o as homepage,m as license,e as main,b as name,r as peerDependencies,k as repository,j as scripts,a as type,f as types,c as version}from'./chunk-
|
|
2
|
-
//# sourceMappingURL=package-
|
|
1
|
+
export{l as author,i as bin,n as bugs,s as default,q as dependencies,d as description,p as devDependencies,g as exports,h as files,o as homepage,m as license,e as main,b as name,r as peerDependencies,k as repository,j as scripts,a as type,f as types,c as version}from'./chunk-4GRKA5XD.js';//# sourceMappingURL=package-LHHQ7BNW.js.map
|
|
2
|
+
//# sourceMappingURL=package-LHHQ7BNW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-LHHQ7BNW.js"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {a,b,c}from'./chunk-JBTEZOY2.js';import'./chunk-LDVLXJLS.js';import'./chunk-3SPXJEOR.js';import {a as a$1,m}from'./chunk-IJ5BS7PM.js';import {x,r,y}from'./chunk-VFOGVWJK.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';import {renderToPipeableStream}from'react-dom/server';import {Writable}from'stream';import {QueryClient,dehydrate}from'@tanstack/react-query';import {jsx}from'react/jsx-runtime';var W=()=>{let r=c();return r?y(r.session.user):null},D=r=>{let t=c();if(t)return t.session.configs[r]?.value};function A(){x(W),r(D);}async function Y(r){let{callContext:t,loadingElement:m$1,routesElement:n,router:o,location:s}=r;A();let l=await a("_system.session.init",{},t),e=new QueryClient({defaultOptions:{queries:{retry:false,gcTime:0}}}),d=o?o({children:n,location:s}):n,i=jsx(a$1,{loadingElement:m$1,children:jsx(m,{client:e,children:d})}),p=await b({callContext:t,queryClient:e,session:{user:l.user,configs:l.configs??{}}},()=>H(i,s)),y=dehydrate(e);return e.clear(),{html:p,sessionState:JSON.stringify({session:l}),queryState:JSON.stringify(y)}}async function Z(r){let{callContext:t,loadingElement:m$1,routesElement:n,router:o,location:s,onShellReady:l,onError:e}=r;A();let d=await a("_system.session.init",{},t),i=new QueryClient({defaultOptions:{queries:{retry:false,gcTime:0}}}),p=o?o({children:n,location:s}):n,y=jsx(a$1,{loadingElement:m$1,children:jsx(m,{client:i,children:p})}),f=null;await new Promise((u,R)=>{b({callContext:t,queryClient:i,session:{user:d.user,configs:d.configs??{}}},()=>{let a=renderToPipeableStream(y,{onShellReady(){f=a,l?.(),u(a);},onShellError(c){R(c);},onError(c){e?.(c);}});return a});});let g=null,I=u=>new Promise((R,a)=>{if(!f){a(new Error("SSR stream was not initialized"));return}let c=new Writable({write(h,x,J){u.write(h,M=>J(M??void 0));},final(h){try{let x=dehydrate(i);g=JSON.stringify(x);}finally{i.clear();}h(),R();}});c.on("error",a),u.on("error",a),f.pipe(c);});return {sessionState:JSON.stringify({session:d}),pipe:I,getQueryState:()=>{if(g===null)throw new Error("getQueryState() called before stream finished");return g}}}function H(r,t){return new Promise((m,n)=>{let o="",s=new Writable({write(e,d,i){o+=e.toString(),i();}}),{pipe:l}=renderToPipeableStream(r,{onAllReady(){s.on("finish",()=>m(o)),s.on("error",n),l(s);},onShellError(e){n(e);},onError(e){console.error("SSR onError (non-fatal):",{location:t,error:e});}});})}export{Y as renderSsrTree,Z as renderSsrTreeStream};//# sourceMappingURL=render-NUGKBTTZ.js.map
|
|
2
|
+
//# sourceMappingURL=render-NUGKBTTZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ssr/render.tsx"],"names":["sessionResolver","ctx","getSsrContext","_parseSessionUser","configResolver","key","ensureSsrResolversInstalled","_setSsrSessionResolver","_setSsrConfigResolver","renderSsrTree","options","callContext","loadingElement","routesElement","router","location","sessionPayload","callInProcessMethod","queryClient","QueryClient","routedTree","tree","jsx","AppProvider","ModelenceQueryProvider","html","runWithSsrContext","renderToString","dehydratedState","dehydrate","renderSsrTreeStream","onShellReady","onError","streamRef","resolve","reject","stream","renderToPipeableStream","error","queryStateJson","pipe","destination","passthrough","Writable","chunk","_encoding","callback","err","buffer","writable"],"mappings":"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","file":"render-NUGKBTTZ.js","sourcesContent":["import React from 'react';\nimport { renderToPipeableStream, type PipeableStream } from 'react-dom/server';\nimport { Writable } from 'node:stream';\nimport { QueryClient, dehydrate, type DehydratedState } from '@tanstack/react-query';\nimport { AppProvider } from '../client/AppProvider';\nimport { ModelenceQueryProvider } from '../client/queryProvider';\nimport { getSsrContext, runWithSsrContext } from './context';\nimport { callInProcessMethod } from './callInProcess';\nimport type { Context } from '../methods/types';\nimport {\n _parseSessionUser,\n _setSsrSessionResolver,\n type SessionInitPayload,\n} from '../client/session';\nimport { _setSsrConfigResolver } from '../config/client';\nimport type { ConfigKey, Configs } from '../config/types';\nimport type { SsrRouter } from '../client/renderApp';\n\nconst sessionResolver = () => {\n const ctx = getSsrContext();\n if (!ctx) {\n return null;\n }\n return _parseSessionUser(ctx.session.user);\n};\n\nconst configResolver = (key: ConfigKey) => {\n const ctx = getSsrContext();\n if (!ctx) {\n return undefined;\n }\n return ctx.session.configs[key]?.value;\n};\n\nfunction ensureSsrResolversInstalled() {\n // Idempotent — safe to call repeatedly. Re-installs the framework's own\n // resolvers if they were swapped out (tests, future reload code).\n _setSsrSessionResolver(sessionResolver);\n _setSsrConfigResolver(configResolver);\n}\n\nexport type SsrRenderResult = {\n html: string;\n /** Inline as <script id=\"__MODELENCE_STATE__\">…</script> */\n sessionState: string;\n /** Inline as <script id=\"__MODELENCE_QUERY_STATE__\">…</script> */\n queryState: string;\n};\n\nexport type SsrRenderOptions = {\n callContext: Context;\n loadingElement: React.ReactNode;\n routesElement: React.ReactNode;\n router?: SsrRouter;\n location?: string;\n};\n\nexport type SsrStreamHandle = {\n /** Session bootstrap payload — safe to inline before the React shell flushes. */\n sessionState: string;\n /**\n * Pipe React's HTML stream into the response. Resolves once every Suspense\n * boundary has settled and the stream has finished writing.\n */\n pipe: (destination: Writable) => Promise<void>;\n /**\n * Read the dehydrated query state. Only call AFTER `pipe()` resolves —\n * queries that resolve mid-stream populate the cache during render.\n */\n getQueryState: () => string;\n};\n\nexport type SsrStreamOptions = SsrRenderOptions & {\n /**\n * Called once React has flushed the shell (head + above-fallback content)\n * and the stream is ready to pipe. The framework uses this hook to write\n * the opening template + state scripts before piping React's HTML.\n */\n onShellReady?: () => void;\n /** Non-fatal SSR errors (Suspense fallbacks, etc.). */\n onError?: (error: unknown) => void;\n};\n\nexport async function renderSsrTree(options: SsrRenderOptions): Promise<SsrRenderResult> {\n const { callContext, loadingElement, routesElement, router, location } = options;\n\n ensureSsrResolversInstalled();\n\n const sessionPayload = await callInProcessMethod<SessionInitPayload>(\n '_system.session.init',\n {},\n callContext\n );\n\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n // Per-request client; release cache + timers immediately after dehydrate.\n gcTime: 0,\n },\n },\n });\n\n const routedTree = router ? router({ children: routesElement, location }) : routesElement;\n\n const tree = (\n <AppProvider loadingElement={loadingElement}>\n <ModelenceQueryProvider client={queryClient}>{routedTree}</ModelenceQueryProvider>\n </AppProvider>\n );\n\n const html = await runWithSsrContext(\n {\n callContext,\n queryClient,\n session: {\n user: sessionPayload.user,\n configs: (sessionPayload.configs as Configs) ?? {},\n },\n },\n () => renderToString(tree, location)\n );\n\n // Safe to dehydrate + clear here: `onAllReady` waits for every Suspense\n // boundary to settle before resolving, so all in-flight queries have\n // populated the cache by this point.\n const dehydratedState: DehydratedState = dehydrate(queryClient);\n queryClient.clear();\n\n return {\n html,\n sessionState: JSON.stringify({ session: sessionPayload }),\n queryState: JSON.stringify(dehydratedState),\n };\n}\n\n/**\n * Streaming variant of {@link renderSsrTree}. Returns a handle that lets the\n * caller flush a template prelude (head + opening shell) as soon as the\n * React shell is ready, pipe the React HTML stream into the response, then\n * append the dehydrated query state once streaming completes.\n *\n * This is what enables fast First Contentful Paint: the browser receives the\n * <head> (with CSS <link> tags) immediately, starts the stylesheet fetch in\n * parallel with the HTML stream, and paints the streamed shell with styles\n * applied — instead of the dev-mode FOUC caused by JS-injected CSS.\n */\nexport async function renderSsrTreeStream(options: SsrStreamOptions): Promise<SsrStreamHandle> {\n const { callContext, loadingElement, routesElement, router, location, onShellReady, onError } =\n options;\n\n ensureSsrResolversInstalled();\n\n const sessionPayload = await callInProcessMethod<SessionInitPayload>(\n '_system.session.init',\n {},\n callContext\n );\n\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n gcTime: 0,\n },\n },\n });\n\n const routedTree = router ? router({ children: routesElement, location }) : routesElement;\n const tree = (\n <AppProvider loadingElement={loadingElement}>\n <ModelenceQueryProvider client={queryClient}>{routedTree}</ModelenceQueryProvider>\n </AppProvider>\n );\n\n let streamRef: PipeableStream | null = null;\n // The shell-ready promise resolves with the PipeableStream as soon as React\n // has rendered above-fallback content. Errors during the shell render\n // reject it so the caller can fall back to a static response.\n const shellReady = new Promise<PipeableStream>((resolve, reject) => {\n // Run the render inside the SSR context so server-rendered components\n // can resolve session/config/query state from the per-request scope.\n runWithSsrContext(\n {\n callContext,\n queryClient,\n session: {\n user: sessionPayload.user,\n configs: (sessionPayload.configs as Configs) ?? {},\n },\n },\n () => {\n const stream = renderToPipeableStream(tree, {\n onShellReady() {\n streamRef = stream;\n onShellReady?.();\n resolve(stream);\n },\n onShellError(error) {\n reject(error);\n },\n onError(error) {\n onError?.(error);\n },\n });\n return stream;\n }\n );\n });\n\n // Surface shell errors synchronously by awaiting before returning the handle.\n await shellReady;\n\n let queryStateJson: string | null = null;\n\n const pipe = (destination: Writable): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (!streamRef) {\n reject(new Error('SSR stream was not initialized'));\n return;\n }\n\n // react-dom calls `.end()` on the destination it pipes into. We need to\n // keep writing AFTER React is done (epilogue + query state script), so\n // we wrap the real destination in a pass-through Writable whose `end()`\n // flushes pending data but does NOT close the underlying response.\n const passthrough = new Writable({\n write(chunk, _encoding, callback) {\n destination.write(chunk, (err) => callback(err ?? undefined));\n },\n final(callback) {\n // Triggered by react-dom's `destination.end()`. Resolve the pipe\n // promise so the caller can write the epilogue, but leave the real\n // response open.\n try {\n const dehydratedState: DehydratedState = dehydrate(queryClient);\n queryStateJson = JSON.stringify(dehydratedState);\n } finally {\n queryClient.clear();\n }\n callback();\n resolve();\n },\n });\n\n passthrough.on('error', reject);\n destination.on('error', reject);\n\n streamRef.pipe(passthrough);\n });\n };\n\n return {\n sessionState: JSON.stringify({ session: sessionPayload }),\n pipe,\n getQueryState: () => {\n if (queryStateJson === null) {\n throw new Error('getQueryState() called before stream finished');\n }\n return queryStateJson;\n },\n };\n}\n\nfunction renderToString(tree: React.ReactElement, location: string | undefined): Promise<string> {\n return new Promise((resolve, reject) => {\n let buffer = '';\n const writable = new Writable({\n write(chunk, _encoding, callback) {\n buffer += chunk.toString();\n callback();\n },\n });\n\n const { pipe } = renderToPipeableStream(tree, {\n onAllReady() {\n writable.on('finish', () => resolve(buffer));\n writable.on('error', reject);\n pipe(writable);\n },\n onShellError(error) {\n reject(error);\n },\n onError(error) {\n // Non-fatal recoverable errors (Suspense fallbacks, etc.). React still\n // ships HTML, but repeated occurrences can mask real bugs — log with\n // request URL for telemetry follow-up.\n console.error('SSR onError (non-fatal):', { location, error });\n },\n });\n });\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export{g as getCallContext,f as startServer}from'./chunk-EPSYTDTF.js';import'./chunk-4GRKA5XD.js';import'./chunk-LDVLXJLS.js';import'./chunk-C3UESBRX.js';import'./chunk-3SPXJEOR.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server-XAIFPVGX.js.map
|
|
2
|
+
//# sourceMappingURL=server-XAIFPVGX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"server-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"server-XAIFPVGX.js"}
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{m as ObjectId,k as ServerChannel,a as consumeRateLimit,c as deleteFile,j as deleteUser,i as disableUser,d as downloadFile,e as getFileUrl,b as getUploadUrl,l as sendEmail,h as startApp}from'./chunk-
|
|
1
|
+
export{m as ObjectId,k as ServerChannel,a as consumeRateLimit,c as deleteFile,j as deleteUser,i as disableUser,d as downloadFile,e as getFileUrl,b as getUploadUrl,l as sendEmail,h as startApp}from'./chunk-EPSYTDTF.js';import'./chunk-4GRKA5XD.js';export{r as LiveData,a as Module,b as Store,q as authenticate,t as createQuery,k as dbUsers,c as schema}from'./chunk-LDVLXJLS.js';import'./chunk-C3UESBRX.js';export{a as getConfig}from'./chunk-3SPXJEOR.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server.js.map
|
|
2
2
|
//# sourceMappingURL=server.js.map
|
package/package.json
CHANGED
package/dist/chunk-S3BSPKUV.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {s as s$1}from'./chunk-7E2S5HNK.js';import {a,b as b$1,c,k as k$1,l,m,n,g,h,f,s,e,i,d,j as j$1,o,t,u,v,w as w$1,x,q as q$1,p,A,y as y$1,z as z$1}from'./chunk-LDVLXJLS.js';import {d as d$1,a as a$4}from'./chunk-C3UESBRX.js';import {a as a$2,f as f$1,e as e$1,g as g$1,c as c$1,h as h$1,k as k$2,j as j$2,d as d$2,i as i$1,l as l$1,m as m$1}from'./chunk-3SPXJEOR.js';import {a as a$3,b as b$2}from'./chunk-5M6FUMUK.js';import {a as a$1}from'./chunk-DO5TZLF5.js';import Ar from'dotenv';import Po from'fs/promises';import so from'os';import J from'path';import {Server}from'socket.io';import {createAdapter}from'@socket.io/mongo-adapter';import {MongoClient,MongoError,MongoServerError}from'mongodb';export{ObjectId as m}from'mongodb';import zr from'bcrypt';import L,{z}from'zod';import {randomBytes,randomUUID}from'crypto';import {createServer,defineConfig,loadConfigFromFile,mergeConfig}from'vite';import Co from'@vitejs/plugin-react';import Be from'fs';import U,{Router}from'express';import gn from'cookie-parser';import hn from'http';var ee=new a("_system",{configSchema:{mongodbUri:{type:"secret",isPublic:false,default:""},mongodbPoolSize:{type:"number",isPublic:false,default:10},"env.type":{type:"string",isPublic:true,default:""},"site.url":{type:"string",isPublic:true,default:""},multiInstance:{type:"boolean",isPublic:false,default:false}}});var P=null;async function kt(){if(P)return P;let e=T();if(!e)throw new Error("MongoDB URI is not set");let t=ee.getConfig("mongodbPoolSize");P=new MongoClient(e,{driverInfo:{name:"Modelence",version:s$1.version},ignoreUndefined:true,maxPoolSize:t});try{return await P.connect(),await P.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),P}catch(r){throw console.error(r),P=null,r}}function T(){return ee.getConfig("mongodbUri")||void 0}function me(){return P}var te=null,jr="_modelenceSocketio",xt=60;async function Hr({httpServer:e,channels:t}){let r=me(),o=!!a$2("_system.multiInstance");console.log("Initializing Socket.IO server...");let n=null;if(o&&r){n=r.db().collection(jr);try{await n.createIndex({createdAt:1},{expireAfterSeconds:xt,background:!0});}catch(i){if(i instanceof Error&&"code"in i&&i.code===85)try{await n.dropIndex("createdAt_1"),await n.createIndex({createdAt:1},{expireAfterSeconds:xt,background:!0});}catch(s){console.error("Failed to recreate index on MongoDB collection for Socket.IO:",s);}else console.error("Failed to create index on MongoDB collection for Socket.IO:",i);}}te=new Server(e,{cors:{origin:"*",methods:["GET","POST"]},adapter:n?createAdapter(n):void 0,transports:["websocket"],perMessageDeflate:false}),te.on("error",i=>{console.error("Socket.IO error:",i);}),te.use(async(i,s)=>{let a=i.handshake.auth.token;try{i.data=await q$1(a);}finally{s();}}),te.on("connection",i=>{i.on("disconnect",()=>{A(i);}),i.on("joinChannel",async s=>{let[a]=s.split(":"),c=false;for(let l of t)if(l.category===a){(!l.canAccessChannel||await l.canAccessChannel(i.data))&&(i.join(s),c=true,i.emit("joinedChannel",s));break}c||i.emit("joinError",{channel:s,error:"Access denied"});}),i.on("leaveChannel",s=>{i.leave(s),console.log(`User ${i.id} left channel ${s}`),i.emit("leftChannel",s);}),i.on("subscribeLiveQuery",s=>y$1(i,s)),i.on("unsubscribeLiveQuery",s=>z$1(i,s));}),console.log("Socket.IO server initialized");}function Gr({category:e,id:t,data:r}){te?.to(`${e}:${t}`).emit(e,r);}var At={init:Hr,broadcast:Gr};async function Rt(e){let t=e.toLowerCase().trim().split("@");if(t.length!==2)return false;let r=t[1];return !!await l.findOne({domain:r})}var Ot={interval:a$1.days(1),async handler(){let e=await fetch("https://disposable.github.io/disposable-email-domains/domains.txt");if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);let r=(await e.text()).split(`
|
|
2
|
-
`).map(i=>i.trim().toLowerCase()).filter(i=>i.length>0),o=new Date,n=500;for(let i=0;i<r.length;i+=n){let s=r.slice(i,i+n);try{await l.insertMany(s.map(a=>({domain:a,addedAt:o})));}catch(a){a&&typeof a=="object"&&"name"in a&&a.name;}}}};var pe=3,D=50,_t=8,Pt=128,Mt=254,Lt=e=>z.string().trim().min(e.min??1,{message:`must be at least ${e.min??1} characters`}).max(e.max,{message:`must be at most ${e.max} characters`}),Oe=e=>z.string().trim().max(e.max,{message:`must be at most ${e.max} characters`}).transform(t=>t===""?void 0:t).optional(),Fr=z.object({firstName:Oe({max:50}),lastName:Oe({max:50}),avatarUrl:Oe({max:400}),handle:Lt({min:pe,max:D})}).strict();function fe(e){let t=Fr.partial().safeParse(e);if(!t.success){let r=t.error.issues[0],o=r.path.join("."),n=o?`${o}: ${r.message}`:r.message;throw new Error(n)}return t.data}function ge(e){return z.string().min(_t,{message:`Password must contain at least ${_t} characters`}).max(Pt,{message:`Password must be at most ${Pt} characters`}).parse(e)}function M(e){return z.string().max(Mt,{message:`Email must be at most ${Mt} characters`}).email({message:"Invalid email address"}).parse(e).toLowerCase()}function Ut(e){return Lt({min:pe,max:D}).parse(e)}function he(e){return {id:e._id,handle:e.handle,roles:e.roles||[],firstName:e.firstName??void 0,lastName:e.lastName??void 0,avatarUrl:e.avatarUrl??void 0}}async function It(e){let t=e.slice(0,D);try{if(!await k$1.findOne({handle:t},{collation:{locale:"en",strength:2}}))return t}catch(n){throw new Error(`Database error while checking handle availability: ${n}`)}let r=51;for(let n=2;n<=r;n++){let i=`_${n}`,s=`${t.slice(0,D-i.length)}${i}`;try{if(!await k$1.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}let o=10;for(let n=0;n<o;n++){let i=`_${randomBytes(3).toString("hex")}`,s=`${t.slice(0,D-i.length)}${i}`;try{if(!await k$1.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}throw new Error(`Could not generate a unique handle for base "${e}" after exhausting all attempts.`)}async function $(e,t,{throwOnConflict:r=true}={}){if(e!=null&&String(e).trim()!==""){let n=Ut(String(e).trim());if(r){if(await k$1.findOne({handle:n},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");return n}return It(n)}let o=t.split("@")[0].padEnd(pe,"_").slice(0,D);return It(o)}var _e=Object.freeze({});function Nt(e){_e=Object.freeze(Object.assign({},_e,e));}function y(){return _e}var Pe=Object.freeze({});function Tt(e){Pe=Object.freeze(Object.assign({},Pe,e));}function b(){return Pe}async function $t(e,{user:t,session:r,connectionInfo:o,res:n}){try{if(!r)throw new Error("Session is not initialized");let i=o?.ip;i&&await k({bucket:"signin",type:"ip",value:i});let s=M(e.email),a=z.string().parse(e.password),c=await k$1.findOne({"emails.address":s,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}}),l=c?.authMethods?.password?.hash;if(!l)throw Dt();if(!c.emails?.find(h=>h.address.toLowerCase()===s)?.verified&&y()?.provider)throw new Error("Your email address hasn't been verified yet. Please check your inbox for the verification email.");if(!await zr.compare(a,l))throw Dt();return await d(r.authToken,c._id),n&&h(n,r.authToken),b().onAfterLogin?.({provider:"email",user:c,session:r,connectionInfo:o}),b().login?.onSuccess?.(c),{user:he(c)}}catch(i){throw i instanceof Error&&(b().onLoginError?.({provider:"email",error:i,session:r,connectionInfo:o}),b().login?.onError?.(i)),i}}async function jt(e$1,{session:t,res:r}){if(!t)throw new Error("Session is not initialized");await e(t.authToken),r&&i(r);}function Dt(){return new Error("Incorrect email/password combination")}async function Ht(e,{user:t}){if(!t)throw new Error("Not authenticated");let r=await k$1.requireById(t.id);return {handle:r.handle,emails:r.emails,authMethods:Object.keys(r.authMethods||{}),firstName:r.firstName??void 0,lastName:r.lastName??void 0,avatarUrl:r.avatarUrl??void 0}}async function Gt(e,{user:t}){if(!t)throw new Error("Not authenticated");let r=await k$1.requireById(t.id),o=fe(e);if(await b().validateProfileUpdate?.(o),"handle"in o&&o.handle!==void 0&&await k$1.findOne({handle:o.handle,_id:{$ne:r._id}},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");if(Object.keys(o).length>0){let n={},i={};for(let[a,c]of Object.entries(o))c===void 0?i[a]="":n[a]=c;let s={};Object.keys(n).length>0&&(s.$set=n),Object.keys(i).length>0&&(s.$unset=i);try{await k$1.updateOne({_id:r._id},s);let a=Object.fromEntries(Object.keys(i).map(c=>[c,void 0]));r={...r,...n,...a};}catch(a){throw a instanceof Error&&"code"in a&&a.code===11e3?new Error("Handle already taken."):a}}return {user:he(r)}}var Me=["google","github"];async function Ft({provider:e},{user:t}){if(!t)throw new Error("You must be signed in to unlink a provider.");if(typeof e!="string"||!Me.includes(e))throw new Error(`Invalid provider. Supported providers are: ${Me.join(", ")}.`);let r=await k$1.requireById(t.id),o=r.authMethods??{};if(!o[e])throw new Error(`${e} is not linked to your account.`);if(Object.values(o).filter(Boolean).length<=1)throw new Error("Cannot unlink your only authentication method. Please add another method first.");let s=Object.keys(o).filter(l=>l!==e&&o[l]),a=s.length>0?{$or:s.map(l=>({[`authMethods.${l}`]:{$exists:true}}))}:{};if((await k$1.updateOne({_id:r._id,...a},{$unset:{[`authMethods.${e}`]:""}})).matchedCount===0)throw new Error("Cannot unlink your only authentication method. Please add another method first.")}var oe=new b$1("_modelenceRateLimits",{schema:{bucket:c.string(),type:c.enum(["ip","user","email"]),value:c.string(),windowMs:c.number(),windowStart:c.date(),windowCount:c.number(),prevWindowCount:c.number(),expiresAt:c.date()},indexes:[{key:{bucket:1,type:1,value:1,windowMs:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]});var Le=[];function Vt(e){if(Le.length>0)throw new Error("Duplicate call to initRateLimits - already initialized");Le=e;}async function k(e){let{bucket:t,type:r,value:o,message:n}=e,i=Le.filter(a=>a.bucket===t&&a.type===r),s=n?()=>new d$1(n):void 0;for(let a of i)await Br(a,o,s);}async function Br(e,t,r){let o=()=>r?r():new d$1(`Rate limit exceeded for ${e.bucket}`),n=await oe.findOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window}),i=Date.now(),s=Math.floor(i/e.window)*e.window,{count:a,modifier:c}=n?Jr(n,s,i):{count:0,modifier:{$setOnInsert:{windowStart:new Date(s),windowCount:1,prevWindowCount:0,expiresAt:new Date(s+e.window+e.window)}}};if(a>=e.limit)throw o();await oe.upsertOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window},c);}function Jr(e,t,r){let o=t-e.windowMs;if(e.windowStart.getTime()===t){let n=e.windowCount,i=e.prevWindowCount,s=1-(r-t)/e.windowMs;return {count:Math.round(n+i*s),modifier:{$inc:{windowCount:1},$setOnInsert:{windowStart:new Date(t),prevWindowCount:0,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}if(e.windowStart.getTime()===o){let n=1-(r-t)/e.windowMs;return {count:Math.round(e.windowCount*n),modifier:{$set:{windowStart:new Date(t),windowCount:1,prevWindowCount:e.windowCount,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}return {count:0,modifier:{$set:{windowStart:new Date(t),windowCount:1,prevWindowCount:0,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}function zt({name:e,email:t,verificationUrl:r}){return `
|
|
3
|
-
<p>Hi${e?` ${e}`:""},</p>
|
|
4
|
-
<p>Please verify your email address ${t} by clicking the link below:</p>
|
|
5
|
-
<p><a href="${r}">${r}</a></p>
|
|
6
|
-
<p>If you did not request this, please ignore this email.</p>
|
|
7
|
-
`}async function Qr(e){let t=await m.findOne({token:e,expiresAt:{$gt:new Date}});if(!t)throw new Error("Invalid or expired verification token");if(!await k$1.findOne({_id:t.userId,status:{$nin:["deleted","disabled"]}}))throw new Error("User not found");let o=t.email;if(!o)throw new Error("Email not found in token");let n=await k$1.findOneAndUpdate({_id:t.userId,status:{$nin:["deleted","disabled"]},"emails.address":o,"emails.verified":{$ne:true}},{$set:{"emails.$.verified":true}},{returnDocument:"after"});if(!n)throw await k$1.findOne({_id:t.userId,"emails.address":o})?new Error("Email is already verified"):new Error("Email address not found for this user");return await m.deleteOne({_id:t._id}),{userDoc:n,email:o}}async function qt(e){let t=a$2("_system.site.url"),r=y().verification?.redirectUrl||y().emailVerifiedRedirectUrl||t||"/";try{let o=z.string().parse(e.query.token),{userDoc:n}=await Qr(o);b().onAfterEmailVerification?.({provider:"email",user:n,session:null,connectionInfo:{baseUrl:t,ip:e.req.ip||e.req.socket.remoteAddress,userAgent:e.headers["user-agent"],acceptLanguage:e.headers["accept-language"],referrer:e.headers.referer}});let{authToken:s}=await g(n._id);return h(e.res,s),{status:301,redirect:`${r}?status=verified`}}catch(o){let n=o instanceof Error?o.message:"An unexpected error occurred";return o instanceof Error&&(b().onEmailVerificationError?.({provider:"email",error:o,session:null,connectionInfo:{baseUrl:t,ip:e.req.ip||e.req.socket.remoteAddress,userAgent:e.headers["user-agent"],acceptLanguage:e.headers["accept-language"],referrer:e.headers.referer}}),console.error("Error verifying email:",o)),{status:301,redirect:`${r}?status=error&message=${encodeURIComponent(n)}`}}}async function Ie({userId:e,email:t,baseUrl:r=a$2("_system.site.url")}){if(y().provider){let o=y().provider,n=randomBytes(32).toString("hex"),i=new Date(Date.now()+a$1.hours(24));await m.insertOne({userId:e,email:t,token:n,createdAt:new Date,expiresAt:i});let s$1=`${r}/api/_internal/auth/verify-email?token=${n}`,c=(y()?.verification?.template||zt)({name:"",email:t,verificationUrl:s$1}),l=s(c);await o?.sendEmail({to:t,from:y()?.from||"noreply@modelence.com",subject:y()?.verification?.subject||"Verify your email address",text:l,html:c});}}var Ue={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function Bt(e,{connectionInfo:t}){let r=M(e.email),o=await k$1.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!o)return Ue;let n=o.emails?.find(i=>i.address.toLowerCase()===r);if(!n||n.verified)return Ue;if(!y().provider)throw new Error("Email provider is not configured");return await k({bucket:"verification",type:"user",value:o._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await Ie({userId:o._id,email:r,baseUrl:t?.baseUrl}),Ue}async function Jt(e,{user:t,session:r,connectionInfo:o}){let n=b();try{let i=e,{firstName:s,lastName:a,avatarUrl:c,handle:l}=i,d=M(i.email),p=ge(i.password),h=o?.ip;if(h&&await k({bucket:"signupAttempt",type:"ip",value:h}),await Rt(d))throw new Error("Please use a permanent email address");let C=await k$1.findOne({"emails.address":d},{collation:{locale:"en",strength:2}});if(C){let ae=C.emails?.find(Y=>Y.address.toLowerCase()===d);throw C.status==="disabled"?new Error("User is marked for deletion, please contact support if you want to restore the account."):new Error(`User with email already exists: ${ae?.address}`)}h&&await k({bucket:"signup",type:"ip",value:h});let E=fe({firstName:s,lastName:a,avatarUrl:c,handle:l});await n.validateSignup?.({email:d,password:p,...E});let R;if(E.handle)R=await $(E.handle,d);else if(n.generateHandle){let ae=await n.generateHandle({email:d,firstName:E.firstName,lastName:E.lastName});R=await $(ae,d,{throwOnConflict:!1});}else R=await $(void 0,d);let xe=await zr.hash(p,10),Q=await k$1.insertOne({handle:R,status:"active",emails:[{address:d,verified:!1}],createdAt:new Date,authMethods:{password:{hash:xe}},...E.firstName!==void 0&&{firstName:E.firstName},...E.lastName!==void 0&&{lastName:E.lastName},...E.avatarUrl!==void 0&&{avatarUrl:E.avatarUrl}}),I=await k$1.findOne({_id:Q.insertedId},{readPreference:"primary"});if(!I)throw new Error("User not found");return await Ie({userId:Q?.insertedId,email:d,baseUrl:o?.baseUrl}),n.onAfterSignup?.({provider:"email",user:I,session:r,connectionInfo:o}),n.signup?.onSuccess?.(I),Q.insertedId}catch(i){throw i instanceof Error&&(n.onSignupError?.({provider:"email",error:i,session:r,connectionInfo:o}),n.signup?.onError?.(i)),i}}function to(e,t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`${e}${t.startsWith("/")?"":"/"}${t}`:e}function ro({email:e,resetUrl:t}){return `
|
|
8
|
-
<p>Hi,</p>
|
|
9
|
-
<p>We received a request to reset your password for ${e}.</p>
|
|
10
|
-
<p>Click the link below to reset your password:</p>
|
|
11
|
-
<p><a href="${t}">${t}</a></p>
|
|
12
|
-
<p>This link will expire in 1 hour.</p>
|
|
13
|
-
<p>If you did not request this password reset, please ignore this email.</p>
|
|
14
|
-
`}var Ne={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function Wt(e,{connectionInfo:t}){let r=M(e.email),o=t?.ip;o&&await k({bucket:"passwordReset",type:"ip",value:o}),await k({bucket:"passwordReset",type:"email",value:r});let n$1=await k$1.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!n$1||!n$1.authMethods?.password)return Ne;let i=y().provider;if(!i)throw new Error("Email provider is not configured");let s$1=randomBytes(32).toString("hex"),a=Date.now(),c=new Date(a),l=new Date(a+a$1.hours(1));await n.insertOne({userId:n$1._id,email:r,token:s$1,createdAt:c,expiresAt:l});let d=a$2("_system.site.url")||t?.baseUrl,h=`${to(d,y().passwordReset?.redirectUrl)}?token=${s$1}`,E=(y()?.passwordReset?.template||ro)({email:r,resetUrl:h,name:""}),R=s(E);return await i.sendEmail({to:r,from:y()?.from||"noreply@modelence.com",subject:y()?.passwordReset?.subject||"Reset your password",text:R,html:E}),Ne}async function Kt(e,{}){let t=z.string().parse(e.token),r=ge(e.password),o=await n.findOne({token:t});if(!o)throw new Error("Invalid or expired reset token");if(o.expiresAt<new Date)throw await n.deleteOne({token:t}),new Error("Reset token has expired");let n$1=await k$1.findOne({_id:o.userId});if(!n$1)throw new Error("User not found");let i=await zr.hash(r,10);return await k$1.updateOne({_id:n$1._id},{$set:{"authMethods.password.hash":i}}),o.email&&await k$1.updateOne({_id:n$1._id,"emails.address":o.email},{$set:{"emails.$.verified":true}}),await f(n$1._id),await n.deleteOne({token:t}),{success:true,message:"Password has been reset successfully"}}function Te(e={}){return [{bucket:"signup",type:"ip",window:a$1.minutes(15),limit:e.signup?.perIp15Minutes??20},{bucket:"signup",type:"ip",window:a$1.days(1),limit:e.signup?.perIpPerDay??200},{bucket:"signupAttempt",type:"ip",window:a$1.minutes(15),limit:e.signupAttempt?.perIp15Minutes??50},{bucket:"signupAttempt",type:"ip",window:a$1.days(1),limit:e.signupAttempt?.perIpPerDay??500},{bucket:"signin",type:"ip",window:a$1.minutes(15),limit:e.signin?.perIp15Minutes??50},{bucket:"signin",type:"ip",window:a$1.days(1),limit:e.signin?.perIpPerDay??500},{bucket:"verification",type:"user",window:a$1.seconds(60),limit:e.verification?.perUserPerMinute??1},{bucket:"verification",type:"user",window:a$1.days(1),limit:e.verification?.perUserPerDay??10},{bucket:"passwordReset",type:"ip",window:a$1.minutes(15),limit:e.passwordReset?.perIp15Minutes??10},{bucket:"passwordReset",type:"ip",window:a$1.days(1),limit:e.passwordReset?.perIpPerDay??100},{bucket:"passwordReset",type:"email",window:a$1.hours(1),limit:e.passwordReset?.perEmailPerHour??5},{bucket:"passwordReset",type:"email",window:a$1.days(1),limit:e.passwordReset?.perEmailPerDay??10}]}var De=new a("_system.user",{stores:[k$1,l,m,n],queries:{getOwnProfile:Ht},mutations:{signupWithPassword:Jt,loginWithPassword:$t,logout:jt,resendEmailVerification:Bt,sendResetPasswordToken:Wt,resetPassword:Kt,updateProfile:Gt,unlinkOAuthProvider:Ft},cronJobs:{updateDisposableEmailList:Ot},rateLimits:Te(),configSchema:{"auth.email.enabled":{type:"boolean",isPublic:true,default:true},"auth.email.from":{type:"string",isPublic:false,default:""},"auth.email.verification":{type:"boolean",isPublic:true,default:false},"auth.google.enabled":{type:"boolean",isPublic:true,default:false},"auth.google.clientId":{type:"string",isPublic:false,default:""},"auth.google.clientSecret":{type:"secret",isPublic:false,default:""},"auth.github.enabled":{type:"boolean",isPublic:true,default:false},"auth.github.clientId":{type:"string",isPublic:false,default:""},"auth.github.clientSecret":{type:"secret",isPublic:false,default:""}},routes:[{path:"/api/_internal/auth/verify-email",handlers:{get:qt}}]});var oo={withoutRemoteServer:{MONGODB_URI:"_system.mongodbUri",MONGODB_POOL_SIZE:"_system.mongodbPoolSize",MODELENCE_AUTH_GOOGLE_ENABLED:"_system.user.auth.google.enabled",MODELENCE_AUTH_GOOGLE_CLIENT_ID:"_system.user.auth.google.clientId",MODELENCE_AUTH_GOOGLE_CLIENT_SECRET:"_system.user.auth.google.clientSecret",MODELENCE_AUTH_GITHUB_ENABLED:"_system.user.auth.github.enabled",MODELENCE_AUTH_GITHUB_CLIENT_ID:"_system.user.auth.github.clientId",MODELENCE_AUTH_GITHUB_CLIENT_SECRET:"_system.user.auth.github.clientSecret",MODELENCE_AUTH_GITHUB_CLIENT_SCOPES:"_system.user.auth.github.scopes",MODELENCE_EMAIL_RESEND_API_KEY:"_system.email.resend.apiKey",MODELENCE_EMAIL_AWS_SES_REGION:"_system.email.awsSes.region",MODELENCE_EMAIL_AWS_SES_ACCESS_KEY_ID:"_system.email.awsSes.accessKeyId",MODELENCE_EMAIL_AWS_SES_SECRET_ACCESS_KEY:"_system.email.awsSes.secretAccessKey",MODELENCE_EMAIL_SMTP_HOST:"_system.email.smtp.host",MODELENCE_EMAIL_SMTP_PORT:"_system.email.smtp.port",MODELENCE_EMAIL_SMTP_USER:"_system.email.smtp.user",MODELENCE_EMAIL_SMTP_PASS:"_system.email.smtp.pass",MODELENCE_SITE_URL:"_system.site.url",MODELENCE_ENV_TYPE:"_system.env.type",MODELENCE_MULTI_INSTANCE:"_system.multiInstance",MODELENCE_ENV:"_system.env",GOOGLE_AUTH_ENABLED:"_system.user.auth.google.enabled",GOOGLE_AUTH_CLIENT_ID:"_system.user.auth.google.clientId",GOOGLE_AUTH_CLIENT_SECRET:"_system.user.auth.google.clientSecret"},withRemoteServer:{MODELENCE_SITE_URL:"_system.site.url"}};function no(e,t){if(t==="number"){let r=Number(e);if(isNaN(r))throw new Error(`Invalid number value for config: ${e}`);return r}if(t==="boolean"){if(e.toLowerCase()==="true")return true;if(e.toLowerCase()==="false")return false;throw new Error(`Invalid boolean value for config: ${e}`)}return e}function io(e,t){let r=[];for(let[o,n]of Object.entries(e)){let i=process.env[o],s=t[n];if(i){let a=s?.type??"string";r.push({key:n,type:a,value:no(i,a)});}}return r}function we(e,t="withoutRemoteServer"){let r=oo[t];return io(r,e)}async function Qt({configSchema:e,cronJobsMetadata:t,stores:r,roles: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=(r??[]).map(a=>({name:a.getName(),schema:a.getSerializedSchema(),collections:[a.getName()],version:2,indexes:a.getIndexes(),searchIndexes:a.getSearchIndexes(),indexCreationMode:a.getIndexCreationMode()})),s=await $e("/api/connect","POST",{hostname:so.hostname(),containerId:n,dataModels:i,configSchema:e,cronJobsMetadata:t,roles:o});if(s.status==="error")throw new Error(s.error);return console.log("Successfully connected to Modelence Cloud"),s}catch(i){throw console.error("Unable to connect to Modelence Cloud:",i),i}}async function Yt(){return $e("/api/configs","GET")}async function Xt(){return await $e("/api/sync","POST",{containerId:process.env.MODELENCE_CONTAINER_ID})}async function $e(e,t,r){return q(e,t,r?JSON.stringify(r):void 0,r?{"Content-Type":"application/json"}:{})}async function q(e,t,r,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 s=await fetch(`${n}${e}`,{method:t,headers:{Authorization:`Bearer ${i}`,...o},body:r});if(!s.ok){let a=await s.text();try{let c=JSON.parse(a);throw new Error(`Unable to connect to Modelence Cloud: HTTP status: ${s.status}, ${c?.error}`)}catch{throw new Error(`Unable to connect to Modelence Cloud: HTTP status: ${s.status}, ${a}`)}}if(!(s.status===204||s.headers?.get("content-length")==="0"))return await s.json()}var je=false,ao=a$1.seconds(10);function Zt(){setInterval(async()=>{if(!je){je=true;try{await Xt();}catch(e){console.error("Error syncing status",e);}try{await co();}catch(e){console.error("Error syncing config",e);}je=false;}},ao);}function He(e){c$1(e),c$1(we(d$2(),"withRemoteServer"));}async function co(){let{configs:e}=await Yt();He(e);}var j=new b$1("_modelenceLocks",{schema:{_id:c.string(),instanceId:c.string(),acquiredAt:c.date(),resource:c.string()},indexes:[{key:{resource:1},unique:true},{key:{resource:1,instanceId:1}},{key:{resource:1,acquiredAt:1}}],indexCreationMode:"blocking"});var H={},er=a$1.seconds(10),nr=randomBytes(32).toString("base64url"),mo=a$1.seconds(30),B=new Map,Ge=e=>e instanceof MongoError&&e.code===11e3,tr=(e,t)=>typeof e.keyPattern=="object"&&e.keyPattern!==null&&Object.prototype.hasOwnProperty.call(e.keyPattern,t),po=async({error:e,resource:t})=>{if(tr(e,"resource"))return true;if(tr(e,"_id"))return false;let r=await j.findOne({resource:t});return !!r&&r._id!==t},rr=async({resource:e,staleThresholdDate:t,instanceId:r})=>{let o=await j.upsertOne({_id:e,$or:[{instanceId:r},{acquiredAt:{$lt:t}}]},{$set:{resource:e,instanceId:r,acquiredAt:new Date},$setOnInsert:{_id:e}});return o.upsertedCount>0||o.modifiedCount>0},ir=async({resource:e,instanceId:t,staleThresholdDate:r})=>{let o=r?{resource:e,_id:{$ne:e},$or:[{instanceId:t},{acquiredAt:{$lt:r}}]}:{resource:e,instanceId:t};return (await j.deleteOne(o)).deletedCount>0},fo=e=>{let t=e,r=B.get(t);r&&(r.stopRequested=true,r.timer&&(clearTimeout(r.timer),r.timer=null),B.delete(t));},or=({resource:e,lockDuration:t,instanceId:r})=>{let o=Math.floor(t/3),n=e,i=B.get(n);if(i&&!i.stopRequested&&i.heartbeatInterval===o&&i.lockDuration===t)return;i&&(i.stopRequested=true,i.timer&&(clearTimeout(i.timer),i.timer=null),B.delete(n));let s={timer:null,stopRequested:false,lockDuration:t,heartbeatInterval:o},a=()=>{s.timer=setTimeout(()=>{G(e,{lockDuration:t,bypassCache:true,instanceId:r}).then(c=>{c||(s.stopRequested=true,i$1(`Lost lock while refreshing heartbeat: ${e}`,{source:"lock",resource:e,instanceId:r}));}).finally(()=>{if(s.stopRequested){B.delete(n);return}a();});},o);};B.set(n,s),a();};async function G(e,{lockDuration:t=mo,successfulLockCacheDuration:r=er,failedLockCacheDuration:o=er,heartbeat:n,bypassCache:i,instanceId:s=nr}={}){let a=Date.now();if(!i&&H[e]&&a<H[e].expiresAt)return H[e].value&&n&&or({resource:e,lockDuration:t,instanceId:s}),H[e].value;let c=new Date(a-t);i$1(`Attempting to acquire lock: ${e}`,{source:"lock",resource:e,instanceId:s});try{let l=await go({resource:e,staleThresholdDate:c,instanceId:s});return H[e]={value:l,expiresAt:a+(l?r:o)},l?(n&&or({resource:e,lockDuration:t,instanceId:s}),i$1(`Lock acquired: ${e}`,{source:"lock",resource:e,instanceId:s})):i$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),l}catch{return H[e]={value:false,expiresAt:a+o},i$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),false}}var go=async({resource:e,staleThresholdDate:t,instanceId:r})=>{try{return await rr({resource:e,staleThresholdDate:t,instanceId:r})}catch(o){if(Ge(o)&&await po({error:o,resource:e})){if(!await ir({resource:e,staleThresholdDate:t,instanceId:r}))return false;try{return await rr({resource:e,staleThresholdDate:t,instanceId:r})}catch(i){if(Ge(i))return false;throw i}}if(Ge(o))return false;throw o}};async function ne(e,{instanceId:t=nr}={}){fo(e);try{let r=await j.deleteOne({_id:e,instanceId:t});return r.deletedCount===0?await ir({resource:e,instanceId:t}):r.deletedCount>0}catch{return false}finally{delete H[e];}}var F={},Fe=null,Ve=new b$1("_modelenceCronJobs",{schema:{alias:c.string(),lastStartDate:c.date().optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function ar(e,{description:t="",interval:r,timeout:o=Math.min(Math.max(r,a$1.minutes(1)),a$1.days(1)),handler:n}){if(F[e])throw new Error(`Duplicate cron job declaration: '${e}' already exists`);if(Fe)throw new Error(`Unable to add a cron job - cron jobs have already been initialized: [${e}]`);if(r<a$1.seconds(5))throw new Error(`Cron job interval should not be less than 5 second [${e}]`);if(o>a$1.days(1))throw new Error(`Cron job timeout should not be longer than 1 day [${e}]`);F[e]={alias:e,params:{description:t,interval:r,timeout:o},handler:n,state:{isRunning:false}};}async function cr(){if(Fe)throw new Error("Cron jobs already started");let e=Object.keys(F);if(e.length>0){let t={alias:{$in:e}},r=await Ve.fetch(t),o=Date.now();r.forEach(n=>{let i=F[n.alias];i&&(i.state.scheduledRunTs=n.lastStartDate?n.lastStartDate.getTime()+i.params.interval:o);}),Object.values(F).forEach(n=>{n.state.scheduledRunTs||(n.state.scheduledRunTs=o);}),Fe=setInterval(ho,a$1.seconds(1));}}async function ho(){let e=Date.now();await G("cron",{successfulLockCacheDuration:a$1.seconds(10),failedLockCacheDuration:a$1.seconds(30)})&&Object.values(F).forEach(async r=>{let{params:o,state:n}=r;if(n.isRunning){n.startTs&&n.startTs+o.timeout<e&&(n.isRunning=false);return}n.scheduledRunTs&&n.scheduledRunTs<=e&&await wo(r);});}async function wo(e){let{alias:t,params:r,handler:o,state:n}=e;n.isRunning=true,n.startTs=Date.now(),await Ve.updateOne({alias:t},{$set:{lastStartDate:new Date(n.startTs)}});let i=l$1("cron",`cron:${t}`);try{await o(),sr(n,r),i.end("success");}catch(s){sr(n,r);let a=s instanceof Error?s:new Error(String(s));m$1(a),i.end("error"),console.error(`Error in cron job '${t}':`,s);}}function sr(e,t){e.scheduledRunTs=e.startTs?e.startTs+t.interval:Date.now(),e.startTs=void 0,e.isRunning=false;}function lr(){return Object.values(F).map(({alias:e,params:t})=>({alias:e,description:t.description,interval:t.interval,timeout:t.timeout}))}var dr=new a("_system.cron",{stores:[Ve]});function ur(e){let t=[...new Set(e)],r=new Map;for(let i of t){let s=i.getChainRoot();r.set(s,s.getChainTail());}let o=[...new Set(r.values())],n=new Map;for(let[i,s]of r){let a=s.getName(),c=n.get(a);if(c!==void 0&&c!==i)throw new Error(`Store collision: multiple unrelated stores use collection name '${a}'. Use .extend() to create a single extension chain instead of independent stores.`);n.set(a,i);}return {storesToInit:t,effectiveStores:o}}var ze=new a("_system.lock",{stores:[j]});var ie=new b$1("_modelenceMigrations",{schema:{version:c.number(),status:c.enum(["completed","failed"]),description:c.string().optional(),output:c.string().optional(),appliedAt:c.date()},indexes:[{key:{version:1},unique:true},{key:{version:1,status:1}}]});async function qe(e,{lockMode:t="acquire"}={}){if(e.length!==0){if(t==="acquire"&&!await G("migrations")){j$2("Another instance is running migrations. Skipping migration run.",{source:"migrations"});return}try{let r=e.map(({version:s})=>s),o=await ie.fetch({version:{$in:r}}),n=new Set(o.map(({version:s})=>s)),i=e.filter(({version:s})=>!n.has(s));if(i.length===0)return;j$2(`Running migrations (${i.length})...`,{source:"migrations"});for(let{version:s,description:a,handler:c}of i){j$2(`Running migration v${s}: ${a}`,{source:"migrations"});try{let d=(await c()||"").toString().trim(),p=15*1024*1024,h=d.length>p?d.slice(0,p)+`
|
|
15
|
-
[Output truncated - exceeded size limit]`:d;await ie.upsertOne({version:s},{$set:{version:s,status:"completed",description:a,output:h,appliedAt:new Date}}),j$2(`Migration v${s} complete`,{source:"migrations"});}catch(l){l instanceof Error&&(await ie.upsertOne({version:s},{$set:{version:s,status:"failed",description:a,output:l.message||"",appliedAt:new Date}}),j$2(`Migration v${s} is failed: ${l.message}`,{source:"migrations"}));}}}finally{t==="acquire"&&await ne("migrations");}}}function mr(e){setTimeout(()=>{qe(e).catch(t=>{console.error("Error running migrations:",t);});},0);}var pr=new a("_system.migration",{stores:[ie]});var fr=new a("_system.rateLimit",{stores:[oe]});async function gr({filePath:e,contentType:t,visibility:r}){return await q("/api/files/upload","POST",JSON.stringify({filePath:e,contentType:t,visibility:r}),{"Content-Type":"application/json"})}async function hr(e){await q("/api/files/delete","POST",JSON.stringify({filePath:e}),{"Content-Type":"application/json"});}async function wr(e){return await q("/api/files/download","POST",JSON.stringify({filePath:e}),{"Content-Type":"application/json"})}async function yr(e){return await q("/api/files/url","POST",JSON.stringify({filePath:e}),{"Content-Type":"application/json"})}var br=new a("_system.files",{queries:{async downloadFile({filePath:e}){return wr(e)},async getFileUrl({filePath:e}){return yr(e)}},mutations:{async getUploadUrl({filePath:e,contentType:t,visibility:r}){return gr({filePath:e,contentType:t,visibility:r})},async deleteFile({filePath:e}){return hr(e)}}});var ye="./.modelence/build/client".replace(/\\/g,"/"),So="./.modelence/build/ssr".replace(/\\/g,"/"),ko="/index.tsx",vr=/<div id="root">\s*<\/div>/,Je=class{constructor(){this.ssrEnabled=false;this.ssrTransportInstalled=false;this.prodEntryLoaded=false;}enableSsr(){this.ssrEnabled=true;}async init({httpServer:t}){if(this.config=await Oo(this.isDev()?t:void 0,{ssr:this.ssrEnabled}),this.isDev()&&(console.log("Starting Vite dev server..."),this.viteServer=await createServer(this.config)),this.ssrEnabled&&!this.ssrTransportInstalled){let{installSsrCallMethodTransport:r}=await import('./transport-BOPYDAVH.js');r(),this.ssrTransportInstalled=true;}}middlewares(){if(this.isDev())return this.viteServer?.middlewares??[];let t=[U.static(ye)];return this.config?.publicDir&&t.push(U.static(this.config.publicDir)),t}async handler(t,r){if(this.ssrEnabled&&xo(t)){try{await this.handleSsr(t,r);}catch(o){this.isDev()&&this.viteServer&&o instanceof Error&&this.viteServer.ssrFixStacktrace(o),console.error("SSR render error:",{url:t.originalUrl,method:t.method,userAgent:t.get("user-agent"),error:o}),this.serveStaticShell(r);}return}if(this.ssrEnabled){r.status(404).end();return}this.serveStaticShell(r);}async handleSsr(t,r){let o=await this.getTemplate(t.originalUrl);await this.evaluateUserSsrEntry();let[{renderSsrTree:n},{_getSsrSnapshot:i},{getCallContext:s}]=await Promise.all([import('./render-LCYTTXNW.js'),import('./renderApp-3FQ6KUQ2.js'),import('./server-UZKGL5C6.js')]),a=await s(t,r),c=i();if(!c)throw new Error("Modelence SSR is enabled but no SSR snapshot was captured. Make sure 'src/client/index.tsx' calls renderApp(...) from 'modelence/client'.");let{html:l,sessionState:d,queryState:p}=await n({callContext:a,loadingElement:c.loadingElement,routesElement:c.routesElement,router:c.router,location:t.originalUrl}),h=`<script id="__MODELENCE_STATE__" type="application/json">${Cr(d)}</script><script id="__MODELENCE_QUERY_STATE__" type="application/json">${Cr(p)}</script>`;if(!vr.test(o))throw new Error('SSR template is missing the expected `<div id="root"></div>` placeholder.');let C=o.replace(vr,()=>`<div id="root">${l}</div>${h}`);r.setHeader("Content-Type","text/html; charset=utf-8"),r.setHeader("Cache-Control","no-store"),r.status(200).end(C);}async getTemplate(t){if(this.isDev()){let o=J.resolve(process.cwd(),"src/client/index.html"),n=Be.readFileSync(o,"utf-8");return this.viteServer&&(n=await this.viteServer.transformIndexHtml(t,n)),n}let r=J.resolve(process.cwd(),ye,"index.html");return Be.readFileSync(r,"utf-8")}async evaluateUserSsrEntry(){if(this.isDev()){if(!this.viteServer)throw new Error("Vite dev server not initialized");await this.viteServer.ssrLoadModule(ko);return}this.prodEntryLoaded||(await import(J.resolve(process.cwd(),So,"index.mjs")),this.prodEntryLoaded=true);}serveStaticShell(t){if(this.isDev())try{t.setHeader("Cache-Control","no-store"),t.sendFile("index.html",{root:"./src/client"});}catch(r){console.error("Error serving index.html:",r),t.status(500).send("Internal Server Error");}else t.sendFile("index.html",{root:ye});}isDev(){return process.env.NODE_ENV!=="production"}};function xo(e){if(e.method!=="GET"&&e.method!=="HEAD"||!(e.get("accept")??"").includes("text/html"))return false;let r=(e.path??e.url??"").split("?")[0];if(r.startsWith("/api/"))return false;let o=r.split("/").pop()??"",n=o.lastIndexOf(".");if(n>0){let i=o.slice(n).toLowerCase();if(i!==".html"&&i!==".htm")return false}return true}function Cr(e){return e.replace(/[<>&\u2028\u2029]/g,t=>`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`)}async function Ao(){let e=process.cwd();try{return (await loadConfigFromFile({command:"serve",mode:"development"},void 0,e))?.config||{}}catch(t){return console.warn("Could not load vite config:",t),{}}}function Ro(e,t){let r=mergeConfig(e,t);if(r.plugins&&Array.isArray(r.plugins)){let o=new Set;r.plugins=r.plugins.flat().filter(n=>{if(!n||typeof n!="object"||Array.isArray(n))return true;let i=n.name;return !i||o.has(i)?false:(o.add(i),true)}).reverse(),r.plugins.reverse();}return r}async function Oo(e,t={}){let r=process.cwd(),o=await Ao(),n=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(a=>Be.existsSync(J.join(r,a))),i=[Co(),_o()];if(n){let a=(await import('vite-plugin-eslint')).default;i.push(a({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:r,overrideConfigFile:J.resolve(r,n)}));}let s=defineConfig({plugins:i,build:{outDir:ye,emptyOutDir:true},server:{middlewareMode:true,hmr:e?{server:e}:void 0},appType:t.ssr?"custom":"spa",root:"./src/client",resolve:{alias:{"@":J.resolve(r,"src").replace(/\\/g,"/")}}});return Ro(s,o)}function _o(){return {name:"modelence-asset-handler",async transform(e,t){if(/\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/.test(t))return process.env.NODE_ENV==="development",e}}}var be=new Je;var We=Object.freeze({});function Sr(e){We=Object.freeze(Object.assign({},We,e));}function kr(){return We}var Ke=Object.freeze({});function xr(e){Ke=Object.freeze(Object.assign({},Ke,e));}function Ee(){return Ke}async function Uo({modules:e=[],roles:t={},defaultRoles:r={},server:o$1=be,migrations:n=[],email:i={},auth:s={},security:a={},websocket:c={},ssr:l=false}){l&&o$1===be&&be.enableSsr(),Ar.config(),Ar.config({path:".modelence.env"});let d=!!process.env.MODELENCE_SERVICE_ENDPOINT;zo().then(()=>{}).catch(()=>{});let p=[De,j$1,dr,pr,fr,ee,ze,br],h=[...p,...e];f$1(),No(p),Io(e),o(t,r);let C=Go(h);e$1(C);let E=To(h),R=Do(h);Fo(h),De.rateLimits=Te(s.rateLimits);let xe=$o(h);Vt(xe);let{storesToInit:Q,effectiveStores:I}=ur(E);if(d){let{configs:Y,environmentId:Lr,appAlias:Ur,environmentAlias:Ir,telemetry:Nr}=await Qt({configSchema:C,cronJobsMetadata:lr(),stores:I,roles:t});He(Y),g$1({environmentId:Lr,appAlias:Ur,environmentAlias:Ir,telemetry:Nr});}else c$1(we(C));if(Nt(i),Tt(s),Sr(a),xr({...c,provider:c.provider||At}),T()){await kt();let Y=[...new Set([...Q,...I])];Vo(Y),await Ho(I,n);}else mr(n);d&&(await h$1(),Zt()),cr().catch(console.error),await Rr(o$1,{combinedModules:h,channels:R});}function Io(e){for(let t$1 of e){for(let[r,o]of Object.entries(t$1.queries))t(`${t$1.name}.${r}`,o);for(let[r,o]of Object.entries(t$1.mutations))u(`${t$1.name}.${r}`,o);}}function No(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))v(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))w$1(`${t.name}.${r}`,o);}}function To(e){return e.flatMap(t=>t.stores)}function Do(e){return e.flatMap(t=>t.channels)}function $o(e){return e.flatMap(t=>t.rateLimits)}function jo(e,t){console.warn(`Failed to create indexes for store '${e}'. Continuing startup.`,t);}var Qe="migrations";async function Ho(e,t){if(!await G(Qe,{lockDuration:a$1.seconds(30),heartbeat:true}))return;let o,n;try{o=e.filter(a=>a.getIndexCreationMode()==="blocking"),n=e.filter(a=>a.getIndexCreationMode()==="background");for(let a of o)await Ye(a,"full");for(let a of n)await Ye(a,"drop-only");}catch(a){throw await ne(Qe),a}let i=(async()=>{for(let a of n)await Ye(a,"create-only");})(),s=qe(t,{lockMode:"skip"});Promise.allSettled([i,s]).then(([a,c])=>{a.status==="rejected"&&console.error("Error creating background indexes:",a.reason),c.status==="rejected"&&console.error("Error running migrations:",c.reason);}).finally(async()=>{await ne(Qe);});}async function Ye(e,t="full"){let r=e.getName();try{await e.createIndexes(t);}catch(o){jo(r,o);}}function Go(e){let t={};for(let r of e)for(let[o,n]of Object.entries(r.configSchema)){let i=`${r.name}.${o}`;if(i in t)throw new Error(`Duplicate config schema key: ${i} (${r.name})`);t[i]=n;}return t}function Fo(e){for(let t of e)for(let[r,o]of Object.entries(t.cronJobs))ar(`${t.name}.${r}`,o);}function Vo(e){let t=me();if(!t)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let r of e)r.init(t);}async function zo(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let t=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",r=process.env.MODELENCE_ENVIRONMENT_ID,o=await qo(),n=await import('./package-J4VDCT4N.js');await fetch(`${t}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:o.name,version:n.default.version,localHostname:so.hostname(),environmentId:r})});}}async function qo(){try{let e=J.join(process.cwd(),"package.json"),t=await Po.readFile(e,"utf-8");return {name:JSON.parse(t).name||"unknown"}}catch{return {name:"unknown"}}}async function Or(e){await m.deleteMany({userId:e}),await n.deleteMany({userId:e});}async function Jo(e){await Or(e),await k$1.updateOne(e,{$set:{status:"disabled",disabledAt:new Date}});}async function Wo(e){await Or(e),await k$1.updateOne({_id:e},{$set:{handle:`deleted-${e}-${randomUUID()}`,status:"deleted",deletedAt:new Date,authMethods:{},emails:[]}});}var Xe=class{constructor(t,r){this.category=t,this.canAccessChannel=r||null;}broadcast(t,r){let o=Ee().provider;if(!o){k$2("Websockets provider should be added to startApp",{});return}o.broadcast({category:this.category,id:t,data:r});}};function Ko(e){if(!y().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return y().provider?.sendEmail(e)}function w(e,t,r){let o=b(),n=e.status(t);if(o.errorComponent)try{let i=o.errorComponent({error:r,statusCode:t});if(i)return n.send(i)}catch(i){console.error("Unhandled error in authConfig.errorComponent:",i);}return n.json({error:r})}async function Ze(e,t){let{authToken:r}=await g(t);h(e,r),e.status(302),e.redirect("/");}async function Yo(e,t,r,o,n){let i=b();try{if(r.status==="disabled"||r.status==="deleted"){w(e,400,"User account is not active.");return}let s={};r.firstName===void 0&&t.firstName&&(s.firstName=t.firstName),r.lastName===void 0&&t.lastName&&(s.lastName=t.lastName),r.avatarUrl===void 0&&t.avatarUrl&&(s.avatarUrl=t.avatarUrl);let a=r;Object.keys(s).length>0&&(await k$1.updateOne({_id:r._id},{$set:s}),a={...r,...s}),await Ze(e,r._id),i.onAfterLogin?.({provider:t.providerName,user:a,session:o,connectionInfo:n}),i.login?.onSuccess?.(a);}catch(s){throw s instanceof Error&&(i.login?.onError?.(s),i.onLoginError?.({provider:t.providerName,error:s,session:o,connectionInfo:n})),s}}async function Xo(e,t,r,o,n){let i=b();if((i.oauthAccountLinking??"manual")==="auto"&&t.emailVerified){if(r.status==="disabled"||r.status==="deleted"){w(e,400,"User account is not active.");return}if(!r.emails?.find(c=>c.address.toLowerCase()===t.email.toLowerCase())?.verified){w(e,400,"User with this email already exists. Please log in instead.");return}try{let c={...r.firstName===void 0&&t.firstName&&{firstName:t.firstName},...r.lastName===void 0&&t.lastName&&{lastName:t.lastName},...r.avatarUrl===void 0&&t.avatarUrl&&{avatarUrl:t.avatarUrl}};if(!((await k$1.updateOne({_id:r._id,status:{$nin:["deleted","disabled"]},$or:[{[`authMethods.${t.providerName}.id`]:{$exists:!1}},{[`authMethods.${t.providerName}.id`]:t.id}]},{$set:{[`authMethods.${t.providerName}.id`]:t.id,...c}})).matchedCount>0)){w(e,400,"User with this email already exists. Please log in instead.");return}await Ze(e,r._id);let p={...r,...c,authMethods:{...r.authMethods,[t.providerName]:{id:t.id}}};i.onAfterLogin?.({provider:t.providerName,user:p,session:o,connectionInfo:n}),i.login?.onSuccess?.(p);return}catch(c){throw c instanceof Error&&(i.login?.onError?.(c),i.onLoginError?.({provider:t.providerName,error:c,session:o,connectionInfo:n})),c}}w(e,400,"User with this email already exists. Please log in instead.");}async function Zo(e,t,r,o){let n=b();try{let i;if(n.generateHandle){let l=await n.generateHandle({email:t.email,firstName:t.firstName,lastName:t.lastName});i=await $(l,t.email,{throwOnConflict:!1});}else i=await $(void 0,t.email);let s={handle:i,status:"active",emails:[{address:t.email,verified:t.emailVerified}],createdAt:new Date,authMethods:{[t.providerName]:{id:t.id}},...t.firstName!==void 0&&{firstName:t.firstName},...t.lastName!==void 0&&{lastName:t.lastName},...t.avatarUrl!==void 0&&{avatarUrl:t.avatarUrl}},a=await k$1.insertOne(s);await Ze(e,a.insertedId);let c=await k$1.findOne({_id:a.insertedId},{readPreference:"primary"});c&&(n.onAfterSignup?.({provider:t.providerName,user:c,session:r,connectionInfo:o}),n.signup?.onSuccess?.(c));}catch(i){throw i instanceof Error&&(n.onSignupError?.({provider:t.providerName,error:i,session:r,connectionInfo:o}),n.signup?.onError?.(i)),i}}function K(e){return `${a$2("_system.site.url")}/api/_internal/auth/${e}/callback`}async function ve(e,t,r){let o=await k$1.findOne({[`authMethods.${r.providerName}.id`]:r.id}),{session:n,connectionInfo:i}=await se(e);if(o)return Yo(t,r,o,n,i);if(!r.email){w(t,400,`Email address is required for ${r.providerName} authentication.`);return}let s;try{s=await k$1.findOne({"emails.address":r.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(a){if(a instanceof Error){let c=b();c.onSignupError?.({provider:r.providerName,error:a,session:n,connectionInfo:i}),c.signup?.onError?.(a);}throw a}return s?Xo(t,r,s,n,i):Zo(t,r,n,i)}function S(e){e.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function W(e){if(e)try{e();}catch(t){console.error("Error executing OAuth hook:",t);}}function Ce(e,t,r){let o=e.query.state,n=e.cookies[r],[i,s]=(n||"").split(":");return !o||!n||o!==i?(w(t,400,"Invalid OAuth state - possible CSRF attack"),null):(t.clearCookie(r),s||"login")}async function Se(e,t,r){let o=b(),{session:n,connectionInfo:i}=await se(e);if(!n?.userId){S(t),w(t,401,"You must be signed in to link a provider.");return}let s=n.userId;try{let a=`authMethods.${r.providerName}.id`;if((await k$1.updateOne({_id:s,status:{$nin:["deleted","disabled"]},$or:[{[a]:{$exists:!1}},{[a]:r.id}]},{$set:{[a]:r.id}})).matchedCount===0){let d=await k$1.findOne({_id:s});if(!d||d.status==="deleted"||d.status==="disabled"){W(()=>o.onOAuthLinkError?.({provider:r.providerName,error:new Error("User account not found or not active"),session:n,connectionInfo:i})),S(t),w(t,400,"User account is not active.");return}let p=d?.authMethods?.[r.providerName]?.id;if(p&&p!==r.id){W(()=>o.onOAuthLinkError?.({provider:r.providerName,error:new Error(`User already has a different ${r.providerName} account linked`),session:n,connectionInfo:i})),S(t),w(t,400,`You have already linked a different ${r.providerName} account.`);return}W(()=>o.onOAuthLinkError?.({provider:r.providerName,error:new Error(`Unexpected OAuth linking state for ${r.providerName}`),session:n,connectionInfo:i})),S(t),w(t,400,`Unable to link ${r.providerName} account.`);return}let l=await k$1.findOne({_id:s},{readPreference:"primary"});l&&W(()=>o.onAfterOAuthLink?.({provider:r.providerName,user:l,session:n,connectionInfo:i})),S(t),t.status(302).redirect("/");}catch(a){if(a instanceof MongoServerError&&a.code===11e3){W(()=>o.onOAuthLinkError?.({provider:r.providerName,error:a,session:n,connectionInfo:i})),S(t),w(t,400,`This ${r.providerName} account is already linked to a different user.`);return}if(a instanceof Error&&W(()=>o.onOAuthLinkError?.({provider:r.providerName,error:a,session:n,connectionInfo:i})),S(t),!t.headersSent)throw a}}function ke(e){return !e||typeof e!="string"?null:e}async function rn(e,t,r,o){let n=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:e,client_id:t,client_secret:r,redirect_uri:o,grant_type:"authorization_code"})});if(!n.ok)throw new Error(`Failed to exchange code for token: ${n.statusText}`);return n.json()}async function on(e){let t=await fetch("https://www.googleapis.com/oauth2/v2/userinfo",{headers:{Authorization:`Bearer ${e}`}});if(!t.ok)throw new Error(`Failed to fetch user info: ${t.statusText}`);return t.json()}async function nn(e,t){let r=ke(e.query.code);if(!r){w(t,400,"Missing authorization code");return}let o=Ce(e,t,"authStateGoogle");if(!o)return;let n=String(a$2("_system.user.auth.google.clientId")),i=String(a$2("_system.user.auth.google.clientSecret")),s=K("google");try{let a=await rn(r,n,i,s),c=await on(a.access_token),l={id:c.id,email:c.email,emailVerified:c.verified_email,providerName:"google",firstName:c.given_name||void 0,lastName:c.family_name||void 0,avatarUrl:c.picture||void 0};o==="link"?await Se(e,t,l):await ve(e,t,l);}catch(a){console.error("Google OAuth error:",a),o==="link"&&S(t),w(t,500,"Authentication failed");}}function sn(){let e=Router(),t=(r,o,n)=>{let i=!!a$2("_system.user.auth.google.enabled"),s=String(a$2("_system.user.auth.google.clientId")),a=String(a$2("_system.user.auth.google.clientSecret"));if(!i||!s||!a){w(o,503,"Google authentication is not configured");return}n();};return e.get("/api/_internal/auth/google",t,(r,o)=>{let n=String(a$2("_system.user.auth.google.clientId")),i=K("google"),s=randomBytes(32).toString("hex"),a=r.query.mode==="link"?"link":"login";o.cookie("authStateGoogle",`${s}:${a}`,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)});let c=new URL("https://accounts.google.com/o/oauth2/v2/auth");c.searchParams.append("client_id",n),c.searchParams.append("redirect_uri",i),c.searchParams.append("response_type","code"),c.searchParams.append("scope","profile email"),c.searchParams.append("access_type","online"),c.searchParams.append("state",s),o.redirect(c.toString());}),e.get("/api/_internal/auth/google/callback",t,nn),e}var _r=sn;async function ln(e,t,r,o){let n=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({client_id:t,client_secret:r,code:e,redirect_uri:o})});if(!n.ok)throw new Error(`Failed to exchange code for token: ${n.statusText}`);return n.json()}async function dn(e){let t=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${e}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok)throw new Error(`Failed to fetch user info: ${t.statusText}`);return t.json()}async function un(e){let t=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${e}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok)throw new Error(`Failed to fetch user emails: ${t.statusText}`);return t.json()}async function mn(e,t){return e.email?e.email:(await un(t)).find(o=>o.primary&&o.verified)?.email??null}async function pn(e,t){let r=ke(e.query.code);if(!r){w(t,400,"Missing authorization code");return}let o=Ce(e,t,"authStateGithub");if(!o)return;let n=String(a$2("_system.user.auth.github.clientId")),i=String(a$2("_system.user.auth.github.clientSecret")),s=K("github");try{let a=await ln(r,n,i,s),c=await dn(a.access_token),l=await mn(c,a.access_token);if(!l){o==="link"&&S(t),w(t,400,"Unable to retrieve a primary verified email from GitHub. Please ensure your GitHub account has a verified email set as primary.");return}let d=c.name?c.name.trim().split(/\s+/):[],p=d[0]||void 0,h=d.length>1?d.slice(1).join(" "):void 0,C={id:String(c.id),email:l,emailVerified:!0,providerName:"github",firstName:p,lastName:h,avatarUrl:c.avatar_url||void 0};o==="link"?await Se(e,t,C):await ve(e,t,C);}catch(a){console.error("GitHub OAuth error:",a),o==="link"&&S(t),w(t,500,"Authentication failed");}}function fn(){let e=Router(),t=(r,o,n)=>{let i=!!a$2("_system.user.auth.github.enabled"),s=String(a$2("_system.user.auth.github.clientId")),a=String(a$2("_system.user.auth.github.clientSecret"));if(!i||!s||!a){w(o,503,"GitHub authentication is not configured");return}n();};return e.get("/api/_internal/auth/github",t,(r,o)=>{let n=String(a$2("_system.user.auth.github.clientId")),i=K("github"),s=a$2("_system.user.auth.github.scopes"),a=s?String(s).split(",").map(p=>p.trim()).join(" "):"user:email",c=randomBytes(32).toString("hex"),l=r.query.mode==="link"?"link":"login";o.cookie("authStateGithub",`${c}:${l}`,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)});let d=new URL("https://github.com/login/oauth/authorize");d.searchParams.append("client_id",n),d.searchParams.append("redirect_uri",i),d.searchParams.append("scope",a),d.searchParams.append("state",c),o.redirect(d.toString());}),e.get("/api/_internal/auth/github/callback",t,pn),e}var Pr=fn;function Mr(e,t,r){return async(o,n,i)=>{let s=o.headers["x-modelence-auth-token"],a={session:null,user:null};if(typeof s=="string"&&T())try{let{session:l,user:d}=await q$1(s);a={session:l,user:d};}catch{}let c=l$1("route",`route:${e.toLowerCase()}:${t}`,{method:e,path:t,query:o.query,body:o.body,params:o.params});try{let l=await r({query:o.query,body:o.body,params:o.params,headers:o.headers,cookies:o.cookies,rawBody:Buffer.isBuffer(o.body)?o.body:void 0,req:o,res:n,next:i},a);c.end(),l&&(n.status(l.status||200),l.redirect&&n.redirect(l.redirect),l.headers&&Object.entries(l.headers).forEach(([d,p])=>{n.setHeader(d,p);}),n.send(l.data));}catch(l){c.end("error"),l instanceof a$4?n.status(l.status).send(l.message):(console.error(`Error in route handler: ${o.path}`),console.error(l),n.status(500).send(String(l)));}}}function wn(e){let t=[];if(!e)return t.push(U.json({limit:"16mb"})),t.push(U.urlencoded({extended:true,limit:"16mb"})),t;if(e.json!==false){let r=typeof e.json=="object"?e.json:{limit:"16mb"};t.push(U.json(r));}if(e.urlencoded!==false){let r=typeof e.urlencoded=="object"?e.urlencoded:{extended:true,limit:"16mb"};t.push(U.urlencoded(r));}if(e.raw){let r=typeof e.raw=="object"?e.raw:{},o={limit:r.limit||"16mb",type:r.type||"*/*"};t.push(U.raw(o));}return t}function yn(e,t){for(let r of t)for(let o of r.routes){let{path:n,handlers:i,body:s}=o,a=wn(s);Object.entries(i).forEach(([c,l])=>{e[c](n,...a,Mr(c,n,l));});}}async function Rr(e,{combinedModules:t,channels:r}){let o=U();o.use(gn()),o.use(vn()),yn(o,t),o.use(U.json({limit:"16mb"})),o.use(U.urlencoded({extended:true,limit:"16mb"})),o.use(_r()),o.use(Pr()),o.post("/api/_internal/auth/set-link-cookie",async(a,c)=>{let{session:l}=await se(a);if(!l?.userId){c.status(401).json({error:"Not authenticated"});return}c.cookie("oauthLinkToken",l.authToken,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/api/_internal/auth/",maxAge:10*60*1e3}),c.json({ok:true});}),o.post("/api/_internal/method/:methodName(*)",async(a,c)=>{let{methodName:l}=a.params,d=await se(a,c);try{let p=a$3(await x(l,a.body.args,d));c.json({data:p,typeMap:b$2(p)});}catch(p){bn(c,l,p);}});let n=hn.createServer(o);await e.init({httpServer:n}),e.middlewares&&o.use(e.middlewares()),o.all("*",(a,c,l)=>{Promise.resolve(e.handler(a,c)).catch(l);}),process.on("unhandledRejection",(a,c)=>{console.error("Unhandled Promise Rejection:"),console.error(a instanceof Error?a.stack:a),console.error("Promise:",c);}),process.on("uncaughtException",a=>{console.error("Uncaught Exception:"),console.error(a.stack),console.trace("Full application stack:");});let i=Ee()?.provider;i&&i.init({httpServer:n,channels:r});let s=process.env.MODELENCE_PORT||process.env.PORT||3e3;n.listen(s,()=>{j$2("Application started",{source:"app"});let a=a$2("_system.site.url")||`http://localhost:${s}`;console.log(`
|
|
16
|
-
Application started on ${a}
|
|
17
|
-
`);});}async function se(e,t=null){let r=(e.path??e.url??"").split("?")[0],o=r.startsWith("/api/_internal/auth/")&&r.endsWith("/callback"),n=e.body??{},i=L.string().nullish().transform(l=>l??null).parse(e.cookies.authToken||(o?e.cookies.oauthLinkToken:null)||n.authToken),s=L.object({screenWidth:L.number(),screenHeight:L.number(),windowWidth:L.number(),windowHeight:L.number(),pixelRatio:L.number(),orientation:L.string().nullable()}).nullish().parse(n.clientInfo)??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},a={ip:Cn(e),userAgent:e.get("user-agent"),acceptLanguage:e.get("accept-language"),referrer:e.get("referrer"),baseUrl:e.protocol+"://"+e.get("host")};if(!!T()){let{session:l,user:d,roles:p}=await q$1(i);return {clientInfo:s,connectionInfo:a,session:l,user:d,roles:p,res:t}}return {clientInfo:s,connectionInfo:a,session:null,user:null,roles:p(),res:t}}function bn(e,t,r){if(r instanceof a$4){r.status>=500&&r.status<600&&console.error(`Error calling ${t}:`,r),e.status(r.status).send(r.message);return}if(r instanceof Error&&r?.constructor?.name==="ZodError"&&"errors"in r){let o="";try{o=En(r);}catch(n){console.error(`Error parsing Zod error in ${t}:`,n),o="Validation failed";}e.status(400).send(o);return}console.error(`Error calling ${t}:`,r),e.status(500).send(r instanceof Error?r.message:String(r));}function En(e){let t=e.flatten(),r=Object.entries(t.fieldErrors).map(([i,s])=>`${i}: ${(s??[]).join(", ")}`),o=t.formErrors;return [...r,...o].filter(Boolean).join("; ")}function vn(){let{frameAncestors:e}=kr(),t=e&&e.length>0,r=t?["'self'",...e].join(" "):"'self'";return (o,n,i)=>{n.setHeader("Content-Security-Policy",`frame-ancestors ${r}`),t||n.setHeader("X-Frame-Options","SAMEORIGIN"),i();}}function Cn(e){let t=e.headers["x-forwarded-for"];if(t)return (Array.isArray(t)?t[0]:t.split(",")[0]).trim();let r=e.ip||e.socket?.remoteAddress;if(r)return r.startsWith("::ffff:")?r.substring(7):r}
|
|
18
|
-
export{k as a,gr as b,hr as c,wr as d,yr as e,Rr as f,se as g,Uo as h,Jo as i,Wo as j,Xe as k,Ko as l};//# sourceMappingURL=chunk-S3BSPKUV.js.map
|
|
19
|
-
//# sourceMappingURL=chunk-S3BSPKUV.js.map
|