modelence 0.18.0-dev.4 → 0.18.0-dev.5
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-3XTC4WGD.js +19 -0
- package/dist/chunk-3XTC4WGD.js.map +1 -0
- package/dist/chunk-TQI5WDPR.js +2 -0
- package/dist/chunk-TQI5WDPR.js.map +1 -0
- package/dist/{chunk-UMT3RHGL.js → chunk-X22U5KA3.js} +3 -3
- package/dist/{chunk-UMT3RHGL.js.map → chunk-X22U5KA3.js.map} +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/{package-VG7P4LRW.js → package-U4D5AOYA.js} +2 -2
- package/dist/{package-VG7P4LRW.js.map → package-U4D5AOYA.js.map} +1 -1
- package/dist/renderApp-ZQEZU2MT.js +2 -0
- package/dist/{renderApp-KKWGQKMM.js.map → renderApp-ZQEZU2MT.js.map} +1 -1
- package/dist/server-Z77W2F6P.js +2 -0
- package/dist/{server-GALICT5J.js.map → server-Z77W2F6P.js.map} +1 -1
- package/dist/server.d.ts +47 -4
- package/dist/server.js +1 -1
- package/dist/{types-DANNMU1V.d.ts → types-BmVlYelB.d.ts} +1 -1
- package/dist/{types-Cq_p_WYj.d.ts → types-V74rNt-g.d.ts} +1 -1
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
- package/dist/chunk-TJ626QWY.js +0 -19
- package/dist/chunk-TJ626QWY.js.map +0 -1
- package/dist/chunk-X6CSJYLY.js +0 -2
- package/dist/chunk-X6CSJYLY.js.map +0 -1
- package/dist/renderApp-KKWGQKMM.js +0 -2
- package/dist/server-GALICT5J.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {a,d,m}from'./chunk-SABBG2XG.js';import {q,s,n,t,v as v$1}from'./chunk-R6OOTUGO.js';import E from'react';import K from'react-dom/client';import {jsx}from'react/jsx-runtime';function h(e){return {getConfig(t){return s(`${e}.${t}`)},query(t,...r){let o=r[0]??{};return {queryKey:[e,t,o],queryFn:()=>q(`${e}.${t}`,o)}},mutation(t){return {mutationFn:r=>q(`${e}.${t}`,r)}},infiniteQuery(t,r){return {queryKey:[e,t,"infinite",r(void 0)],initialPageParam:void 0,queryFn:({pageParam:o})=>q(`${e}.${t}`,r(o))}}}}var b=h("_system");var M=class{constructor(t,r){this.category=t,this.onMessage=r;}init(){d()?.on({category:this.category,listener:this.onMessage});}joinChannel(t){d()?.joinChannel({category:this.category,id:t});}leaveChannel(t){d()?.leaveChannel({category:this.category,id:t});}};async function k(e,{filePath:t,contentType:r,visibility:o}){let{url:l,fields:d,filePath:c}=await q("_system.files.getUploadUrl",{filePath:t,contentType:r,visibility:o}),i=new FormData;for(let[p,u]of Object.entries(d))i.append(p,u);i.append("file",e);let s=await fetch(l,{method:"POST",body:i});if(!s.ok)throw new Error(`Failed to upload file: HTTP status: ${s.status}`);return {filePath:c}}async function F(e){await q("_system.files.deleteFile",{filePath:e});}async function _(e){return q("_system.files.downloadFile",{filePath:e})}async function w(e){return q("_system.files.getFileUrl",{filePath:e})}var A="useClient"in E?E.useClient(a):a;var C="__MODELENCE_STATE__";function U(){return typeof document>"u"?false:document.getElementById(C)!==null}function Q(){if(typeof document>"u")return null;let e=document.getElementById(C);if(!e)return null;try{return JSON.parse(e.textContent??"")}catch(t){return console.error("Modelence: failed to parse SSR state",t),null}}var v="__modelence_ssr_snapshot__";function H(e){globalThis[v]=e;}function We(){return globalThis[v]??null}function O(e){if(typeof window>"u"){H(e);return}let{loadingElement:t$1,routesElement:r,favicon:o,errorHandler:l,router:d}=e;l&&n(l),window.addEventListener("unload",()=>{});let c=U(),i=Q();i?.session&&(t(i.session),v$1());let s=document.getElementById("root"),p=d?d({children:r}):r,u=jsx(E.StrictMode,{children:jsx(A,{loadingElement:t$1,children:jsx(m,{children:p})})});if(c?K.hydrateRoot(s,u):K.createRoot(s).render(u),o){let T=document.querySelector("link[rel~='icon']");if(T)T.href=o;else {let f=document.createElement("link");f.rel="icon",f.href=o,document.head.appendChild(f);}}}export{h as a,b,We as c,O as d,M as e,k as f,F as g,_ as h,w as i,A as j};//# sourceMappingURL=chunk-TQI5WDPR.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-TQI5WDPR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/module.ts","../src/system/client.ts","../src/websocket/clientChannel.ts","../src/files/client.ts","../src/client.ts","../src/client/renderApp.tsx"],"names":["createClientModule","moduleName","key","getConfig","name","rest","args","callMethod","getArgs","pageParam","systemConfig","ClientChannel","category","onMessage","getWebsocketClientProvider","id","uploadFile","file","filePath","contentType","visibility","url","fields","resolvedFilePath","formData","value","uploadResponse","deleteFile","downloadFile","getFileUrl","AppProvider","React","SSR_STATE_SCRIPT_ID","hasSsrMarker","readSsrState","node","e","SNAPSHOT_KEY","setSnapshot","snapshot","_getSsrSnapshot","renderApp","options","loadingElement","routesElement","favicon","errorHandler","router","setErrorHandler","isHydrating","ssrState","hydrateSession","startSessionHeartbeat","container","routedTree","tree","jsx","ModelenceQueryProvider","ReactDOM","link","newLink"],"mappings":"oLAuFO,SAASA,CAAAA,CAA8CC,CAAAA,CAAoB,CAChF,OAAO,CACL,SAAA,CACEC,CAAAA,CACqD,CAErD,OAAOC,CAAAA,CAAiB,CAAA,EAAGF,CAAU,CAAA,CAAA,EAAIC,CAAG,CAAA,CAAE,CAChD,CAAA,CAEA,KAAA,CACEE,CAAAA,CAAAA,GACGC,EAGH,CACA,IAAMC,CAAAA,CAAQD,CAAAA,CAAK,CAAC,CAAA,EAAK,EAAC,CAC1B,OAAO,CACL,QAAA,CAAU,CAACJ,CAAAA,CAAYG,CAAAA,CAAME,CAAI,CAAA,CACjC,OAAA,CAAS,IACPC,CAAAA,CACE,CAAA,EAAGN,CAAU,CAAA,CAAA,EAAIG,CAAI,CAAA,CAAA,CACrBE,CACF,CACJ,CACF,CAAA,CAEA,QAAA,CAAwDF,CAAAA,CAAS,CAC/D,OAAO,CACL,UAAA,CACEE,CAAAA,EAEAC,CAAAA,CACE,CAAA,EAAGN,CAAU,CAAA,CAAA,EAAIG,CAAI,CAAA,CAAA,CACrBE,CACF,CACJ,CACF,CAAA,CAUA,aAAA,CACEF,CAAAA,CACAI,CAAAA,CACA,CACA,OAAO,CACL,QAAA,CAAU,CAACP,CAAAA,CAAYG,CAAAA,CAAM,UAAA,CAAYI,CAAAA,CAAQ,MAAS,CAAC,CAAA,CAE3D,gBAAA,CAAkB,MAAA,CAClB,OAAA,CAAS,CAAC,CACR,UAAAC,CACF,CAAA,GAGEF,CAAAA,CACE,CAAA,EAAGN,CAAU,CAAA,CAAA,EAAIG,CAAI,CAAA,CAAA,CACrBI,CAAAA,CAAQC,CAAS,CACnB,CACJ,CACF,CACF,CACF,CCtJO,IAAMC,CAAAA,CAAeV,CAAAA,CAAwC,SAAS,ECDtE,IAAMW,CAAAA,CAAN,KAAiC,CAItC,WAAA,CAAYC,CAAAA,CAAkBC,CAAAA,CAA8B,CAC1D,IAAA,CAAK,QAAA,CAAWD,CAAAA,CAChB,KAAK,SAAA,CAAYC,EACnB,CAEA,IAAA,EAAO,CACLC,CAAAA,EAA2B,EAAG,EAAA,CAAG,CAC/B,QAAA,CAAU,IAAA,CAAK,QAAA,CACf,QAAA,CAAU,IAAA,CAAK,SACjB,CAAC,EACH,CAEA,WAAA,CAAYC,CAAAA,CAAY,CACtBD,CAAAA,EAA2B,EAAG,WAAA,CAAY,CACxC,QAAA,CAAU,IAAA,CAAK,QAAA,CACf,EAAA,CAAAC,CACF,CAAC,EACH,CAEA,YAAA,CAAaA,CAAAA,CAAY,CACvBD,CAAAA,EAA2B,EAAG,YAAA,CAAa,CACzC,QAAA,CAAU,IAAA,CAAK,QAAA,CACf,EAAA,CAAAC,CACF,CAAC,EACH,CACF,EClBA,eAAsBC,CAAAA,CACpBC,CAAAA,CACA,CAAE,QAAA,CAAAC,CAAAA,CAAU,WAAA,CAAAC,CAAAA,CAAa,UAAA,CAAAC,CAAW,CAAA,CACT,CAC3B,GAAM,CACJ,GAAA,CAAAC,CAAAA,CACA,OAAAC,CAAAA,CACA,QAAA,CAAUC,CACZ,CAAA,CAAI,MAAMhB,CAAAA,CAA+B,4BAAA,CAA8B,CACrE,QAAA,CAAAW,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CACF,CAAC,CAAA,CAEKI,CAAAA,CAAW,IAAI,QAAA,CACrB,IAAA,GAAW,CAACtB,CAAAA,CAAKuB,CAAK,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQH,CAAM,CAAA,CAC9CE,CAAAA,CAAS,MAAA,CAAOtB,CAAAA,CAAKuB,CAAK,EAE5BD,CAAAA,CAAS,MAAA,CAAO,MAAA,CAAQP,CAAI,CAAA,CAE5B,IAAMS,CAAAA,CAAiB,MAAM,KAAA,CAAML,CAAAA,CAAK,CACtC,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMG,CACR,CAAC,EAED,GAAI,CAACE,CAAAA,CAAe,EAAA,CAClB,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuCA,CAAAA,CAAe,MAAM,CAAA,CAAE,CAAA,CAGhF,OAAO,CAAE,QAAA,CAAUH,CAAiB,CACtC,CAEA,eAAsBI,CAAAA,CAAWT,CAAAA,CAAiC,CAChE,MAAMX,CAAAA,CAAW,0BAAA,CAA4B,CAAE,QAAA,CAAAW,CAAS,CAAC,EAC3D,CAEA,eAAsBU,CAAAA,CAAaV,CAAAA,CAAoD,CACrF,OAAOX,CAAAA,CAAW,4BAAA,CAA8B,CAAE,QAAA,CAAAW,CAAS,CAAC,CAC9D,CAEA,eAAsBW,CAAAA,CAAWX,CAAAA,CAA4C,CAC3E,OAAOX,EAAW,0BAAA,CAA4B,CAAE,QAAA,CAAAW,CAAS,CAAC,CAC5D,CC9CO,IAAMY,CAAAA,CACX,WAAA,GAAeC,CAAAA,CAEXA,CAAAA,CAAM,SAAA,CAAUD,CAAmB,CAAA,CACnCA,ECNN,IAAME,CAAAA,CAAsB,qBAAA,CAM5B,SAASC,CAAAA,EAAwB,CAC/B,OAAI,OAAO,QAAA,CAAa,GAAA,CACf,KAAA,CAEF,QAAA,CAAS,cAAA,CAAeD,CAAmB,CAAA,GAAM,IAC1D,CAEA,SAASE,CAAAA,EAAgC,CACvC,GAAI,OAAO,QAAA,CAAa,GAAA,CACtB,OAAO,IAAA,CAGT,IAAMC,CAAAA,CAAO,QAAA,CAAS,cAAA,CAAeH,CAAmB,CAAA,CACxD,GAAI,CAACG,CAAAA,CACH,OAAO,IAAA,CAGT,GAAI,CACF,OAAO,IAAA,CAAK,KAAA,CAAMA,CAAAA,CAAK,WAAA,EAAe,EAAE,CAC1C,OAASC,CAAAA,CAAG,CAIV,OAAA,OAAA,CAAQ,KAAA,CAAM,sCAAA,CAAwCA,CAAC,CAAA,CAChD,IACT,CACF,CAiBA,IAAMC,CAAAA,CAAe,4BAAA,CAMrB,SAASC,CAAAA,CAAYC,CAAAA,CAAmC,CACrD,UAAA,CAAkCF,CAAY,CAAA,CAAIE,EACrD,CAGO,SAASC,EAAAA,EAA2C,CACzD,OAAQ,UAAA,CAAkCH,CAAY,CAAA,EAAK,IAC7D,CAEO,SAASI,EAAUC,CAAAA,CAA2B,CACnD,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjCJ,CAAAA,CAAYI,CAAO,CAAA,CACnB,MACF,CAEA,GAAM,CAAE,cAAA,CAAAC,GAAAA,CAAgB,aAAA,CAAAC,CAAAA,CAAe,OAAA,CAAAC,CAAAA,CAAS,YAAA,CAAAC,CAAAA,CAAc,MAAA,CAAAC,CAAO,CAAA,CAAIL,CAAAA,CAErEI,CAAAA,EACFE,CAAAA,CAAgBF,CAAY,CAAA,CAG9B,MAAA,CAAO,gBAAA,CAAiB,SAAU,IAAM,CAExC,CAAC,CAAA,CAUD,IAAMG,CAAAA,CAAchB,CAAAA,EAAa,CAC3BiB,CAAAA,CAAWhB,CAAAA,EAAa,CAC1BgB,CAAAA,EAAU,OAAA,GACZC,CAAAA,CAAeD,CAAAA,CAAS,OAAO,CAAA,CAC/BE,GAAAA,EAAsB,CAAA,CAGxB,IAAMC,CAAAA,CAAY,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA,CAC1CC,CAAAA,CAAaP,CAAAA,CAASA,CAAAA,CAAO,CAAE,QAAA,CAAUH,CAAc,CAAC,EAAIA,CAAAA,CAC5DW,CAAAA,CACJC,GAAAA,CAACzB,CAAAA,CAAM,UAAA,CAAN,CACC,QAAA,CAAAyB,GAAAA,CAAC1B,CAAAA,CAAA,CAAY,cAAA,CAAgBa,GAAAA,CAC3B,QAAA,CAAAa,GAAAA,CAACC,CAAAA,CAAA,CAAwB,QAAA,CAAAH,CAAAA,CAAW,CAAA,CACtC,CAAA,CACF,CAAA,CASF,GANIL,CAAAA,CACFS,CAAAA,CAAS,WAAA,CAAYL,CAAAA,CAAWE,CAAI,CAAA,CAEpCG,CAAAA,CAAS,UAAA,CAAWL,CAAS,CAAA,CAAE,OAAOE,CAAI,CAAA,CAGxCV,CAAAA,CAAS,CACX,IAAMc,CAAAA,CAAO,QAAA,CAAS,aAAA,CAAc,mBAAmB,CAAA,CACvD,GAAKA,CAAAA,CAMHA,CAAAA,CAAK,IAAA,CAAOd,CAAAA,CAAAA,KANH,CACT,IAAMe,CAAAA,CAAU,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA,CAC7CA,CAAAA,CAAQ,GAAA,CAAM,MAAA,CACdA,CAAAA,CAAQ,IAAA,CAAOf,CAAAA,CACf,QAAA,CAAS,IAAA,CAAK,WAAA,CAAYe,CAAO,EACnC,CAGF,CACF","file":"chunk-TQI5WDPR.js","sourcesContent":["'use client';\n\nimport type { ObjectId } from 'mongodb';\nimport type { ConfigParams, ConfigType, ValueType } from '../config/types';\nimport { callMethod, type MethodArgs } from './method';\nimport type { AnyMethodShape } from '../methods/types';\n\n// Pulls the config store value without importing server-side code\nimport { getConfig as _getClientConfig } from '../config/client';\n\n// ── type helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Recursively maps ObjectId → string to match the sanitized runtime values\n * sent over the wire. Dates are preserved (revived via typeMap on the client).\n */\ntype Sanitized<T> = T extends ObjectId\n ? string\n : T extends Date\n ? Date\n : T extends (infer U)[]\n ? Sanitized<U>[]\n : T extends object\n ? { [K in keyof T]: Sanitized<T[K]> }\n : T;\n\ntype ExtractArgs<M> = M extends (args: infer A, ...rest: any[]) => any // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A\n : M extends { handler: (args: infer A, ...rest: any[]) => any } // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A\n : MethodArgs;\n\ntype ExtractResult<M> = M extends (...args: any[]) => Promise<infer R> // eslint-disable-line @typescript-eslint/no-explicit-any\n ? Sanitized<R>\n : M extends { handler: (...args: any[]) => Promise<infer R> } // eslint-disable-line @typescript-eslint/no-explicit-any\n ? Sanitized<R>\n : unknown;\n\ntype PublicKeyOf<TSchema extends Record<string, ConfigParams>> = {\n [K in keyof TSchema as TSchema[K] extends ConfigParams<ConfigType, true>\n ? string & K\n : never]: ValueType<TSchema[K]['type']>;\n};\n\ntype AnyModule = {\n name: string;\n configSchema: Record<string, ConfigParams>;\n queries: Record<string, AnyMethodShape>;\n mutations: Record<string, AnyMethodShape>;\n};\n\n// ── createClientModule ────────────────────────────────────────────────────────\n\n/**\n * Creates a typed client accessor for a module's public configs, queries, and mutations.\n *\n * Use `import type` to reference the module so no server code is bundled on the client.\n * Arg and return types for queries and mutations are inferred automatically from the\n * server-side handler signatures.\n *\n * @param moduleName - The module's name as passed to `new Module(name, ...)`.\n *\n * @example\n * ```ts\n * // src/client/payments.ts\n * import type paymentsModule from '../server/payments';\n * import { createClientModule } from 'modelence/client';\n *\n * export const payments = createClientModule<typeof paymentsModule>('payments');\n * ```\n *\n * ```ts\n * // src/components/Checkout.tsx\n * import { useQuery, useMutation } from '@tanstack/react-query';\n * import { payments } from '../client/payments';\n *\n * // Typed config — public keys only, private and secret keys excluded:\n * const currency = payments.getConfig('currency'); // string | undefined\n *\n * // Typed query — pass directly to useQuery:\n * const { data: products } = useQuery(payments.query('getProducts', { page: 1 }));\n *\n * // Typed mutation — pass directly to useMutation:\n * const { mutate: charge } = useMutation(payments.mutation('charge'));\n * charge({ amount: 100 }); // args typed from handler signature\n * ```\n */\nexport function createClientModule<TModule extends AnyModule>(moduleName: string) {\n return {\n getConfig<K extends keyof PublicKeyOf<TModule['configSchema']> & string>(\n key: K\n ): PublicKeyOf<TModule['configSchema']>[K] | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return _getClientConfig(`${moduleName}.${key}`) as any;\n },\n\n query<K extends keyof TModule['queries'] & string>(\n name: K,\n ...rest: {} extends ExtractArgs<TModule['queries'][K]>\n ? [args?: ExtractArgs<TModule['queries'][K]>]\n : [args: ExtractArgs<TModule['queries'][K]>]\n ) {\n const args = (rest[0] ?? {}) as ExtractArgs<TModule['queries'][K]>;\n return {\n queryKey: [moduleName, name, args] as const,\n queryFn: (): Promise<ExtractResult<TModule['queries'][K]>> =>\n callMethod<ExtractResult<TModule['queries'][K]>>(\n `${moduleName}.${name}`,\n args as MethodArgs\n ),\n };\n },\n\n mutation<K extends keyof TModule['mutations'] & string>(name: K) {\n return {\n mutationFn: (\n args: ExtractArgs<TModule['mutations'][K]>\n ): Promise<ExtractResult<TModule['mutations'][K]>> =>\n callMethod<ExtractResult<TModule['mutations'][K]>>(\n `${moduleName}.${name}`,\n args as MethodArgs\n ),\n };\n },\n\n /**\n * Returns options for `useInfiniteQuery`. The `getArgs` callback receives the\n * current `pageParam` and returns the args to pass to the query handler.\n * Spread the result into `useInfiniteQuery` alongside `getNextPageParam`.\n *\n * Annotate the `pageParam` type in the callback so TypeScript can infer the\n * page param type — no manual generic needed on `useInfiniteQuery`.\n */\n infiniteQuery<K extends keyof TModule['queries'] & string, TPageParam = unknown>(\n name: K,\n getArgs: (pageParam: TPageParam | undefined) => ExtractArgs<TModule['queries'][K]>\n ) {\n return {\n queryKey: [moduleName, name, 'infinite', getArgs(undefined)] as const,\n // Included so TanStack infers TPageParam from the callback type, not from a bare `undefined`.\n initialPageParam: undefined as TPageParam | undefined,\n queryFn: ({\n pageParam,\n }: {\n pageParam: TPageParam | undefined;\n }): Promise<ExtractResult<TModule['queries'][K]>> =>\n callMethod<ExtractResult<TModule['queries'][K]>>(\n `${moduleName}.${name}`,\n getArgs(pageParam) as MethodArgs\n ),\n };\n },\n };\n}\n","import type systemModule from './index';\nimport { createClientModule } from '../client/module';\n\nexport const systemConfig = createClientModule<typeof systemModule>('_system');\n","import { getWebsocketClientProvider } from './client';\n\nexport class ClientChannel<T = unknown> {\n public readonly category: string;\n private readonly onMessage: (data: T) => void;\n\n constructor(category: string, onMessage: (data: T) => void) {\n this.category = category;\n this.onMessage = onMessage;\n }\n\n init() {\n getWebsocketClientProvider()?.on({\n category: this.category,\n listener: this.onMessage,\n });\n }\n\n joinChannel(id: string) {\n getWebsocketClientProvider()?.joinChannel({\n category: this.category,\n id,\n });\n }\n\n leaveChannel(id: string) {\n getWebsocketClientProvider()?.leaveChannel({\n category: this.category,\n id,\n });\n }\n}\n","import { callMethod } from '../client/method';\nimport type { FileVisibility, GetUploadUrlResult } from './types';\n\ntype UploadFileParams = {\n filePath: string;\n contentType: string;\n visibility: FileVisibility;\n};\n\ntype UploadFileResult = {\n filePath: string;\n};\n\nexport async function uploadFile(\n file: File | Blob,\n { filePath, contentType, visibility }: UploadFileParams\n): Promise<UploadFileResult> {\n const {\n url,\n fields,\n filePath: resolvedFilePath,\n } = await callMethod<GetUploadUrlResult>('_system.files.getUploadUrl', {\n filePath,\n contentType,\n visibility,\n });\n\n const formData = new FormData();\n for (const [key, value] of Object.entries(fields)) {\n formData.append(key, value);\n }\n formData.append('file', file);\n\n const uploadResponse = await fetch(url, {\n method: 'POST',\n body: formData,\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Failed to upload file: HTTP status: ${uploadResponse.status}`);\n }\n\n return { filePath: resolvedFilePath };\n}\n\nexport async function deleteFile(filePath: string): Promise<void> {\n await callMethod('_system.files.deleteFile', { filePath });\n}\n\nexport async function downloadFile(filePath: string): Promise<{ downloadUrl: string }> {\n return callMethod('_system.files.downloadFile', { filePath });\n}\n\nexport async function getFileUrl(filePath: string): Promise<{ url: string }> {\n return callMethod('_system.files.getFileUrl', { filePath });\n}\n","import React from 'react';\n\nimport { AppProvider as OriginalAppProvider } from './client/AppProvider';\n\nexport { getConfig } from './config/client';\nexport { createClientModule } from './client/module';\nexport type { ValueType } from './config/types';\nexport { systemConfig } from './system/client';\n\nexport const AppProvider =\n 'useClient' in React\n ? // @ts-ignore: React.useClient only exists in Next.js\n React.useClient(OriginalAppProvider)\n : OriginalAppProvider;\n\nexport { renderApp } from './client/renderApp';\nexport { ModelenceQueryProvider } from './client/queryProvider';\nexport {\n modelenceQuery,\n modelenceLiveQuery,\n modelenceMutation,\n createQueryKey,\n connectModelenceQueryClient,\n disconnectModelenceQueryClient,\n ModelenceQueryClient,\n type ModelenceQueryKey,\n} from './client/query';\nexport { callMethod, MethodError, type MethodArgs, type CallMethodOptions } from './client/method';\nexport { useSession } from './client/session';\nexport {\n signupWithPassword,\n loginWithPassword,\n verifyEmail,\n updateProfile,\n resendEmailVerification,\n logout,\n sendResetPasswordToken,\n resetPassword,\n linkOAuthProvider,\n unlinkOAuthProvider,\n type UserInfo,\n} from './auth/client';\nexport {\n getWebsocketClientProvider,\n setWebsocketClientProvider,\n startWebsockets,\n subscribeLiveQuery,\n} from './websocket/client';\nexport { ClientChannel } from './websocket/clientChannel';\nexport { getLocalStorageSession } from './client/localStorage';\nexport { uploadFile, deleteFile, downloadFile, getFileUrl } from './files/client';\n","import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { AppProvider } from '../client';\nimport { setErrorHandler, ErrorHandler } from './errorHandler';\nimport { hydrateSession, startSessionHeartbeat, type SessionInitPayload } from './session';\nimport { ModelenceQueryProvider } from './queryProvider';\n\nconst SSR_STATE_SCRIPT_ID = '__MODELENCE_STATE__';\n\ntype SsrState = {\n session?: SessionInitPayload;\n};\n\nfunction hasSsrMarker(): boolean {\n if (typeof document === 'undefined') {\n return false;\n }\n return document.getElementById(SSR_STATE_SCRIPT_ID) !== null;\n}\n\nfunction readSsrState(): SsrState | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const node = document.getElementById(SSR_STATE_SCRIPT_ID);\n if (!node) {\n return null;\n }\n\n try {\n return JSON.parse(node.textContent ?? '') as SsrState;\n } catch (e) {\n // The script tag still signals that SSR ran — the caller must hydrate,\n // not createRoot, even if the payload is unreadable. Session bootstrap\n // is the only thing we lose here.\n console.error('Modelence: failed to parse SSR state', e);\n return null;\n }\n}\n\nexport type SsrRouter = (props: {\n children: React.ReactNode;\n location?: string;\n}) => React.ReactElement;\n\nexport interface RenderAppOptions {\n loadingElement: React.ReactNode;\n routesElement: React.ReactNode;\n favicon?: string;\n errorHandler?: ErrorHandler;\n router?: SsrRouter;\n}\n\n// Shared on globalThis because Vite's ssrLoadModule loads the user's entry\n// in a separate module graph from the framework runtime.\nconst SNAPSHOT_KEY = '__modelence_ssr_snapshot__';\n\ntype GlobalWithSnapshot = typeof globalThis & {\n [SNAPSHOT_KEY]?: RenderAppOptions | null;\n};\n\nfunction setSnapshot(snapshot: RenderAppOptions | null) {\n (globalThis as GlobalWithSnapshot)[SNAPSHOT_KEY] = snapshot;\n}\n\n/** @internal Used by the SSR runtime after evaluating the user's entry. */\nexport function _getSsrSnapshot(): RenderAppOptions | null {\n return (globalThis as GlobalWithSnapshot)[SNAPSHOT_KEY] ?? null;\n}\n\nexport function renderApp(options: RenderAppOptions) {\n if (typeof window === 'undefined') {\n setSnapshot(options);\n return;\n }\n\n const { loadingElement, routesElement, favicon, errorHandler, router } = options;\n\n if (errorHandler) {\n setErrorHandler(errorHandler);\n }\n\n window.addEventListener('unload', () => {\n // Empty 'unload' handler prevents bfcache in most browsers.\n });\n\n // ORDER MATTERS: hydrate session BEFORE building the React tree / calling\n // hydrateRoot, so `isSessionInitialized()` is true on the first render and\n // AppProvider's initial `isLoading` matches the server-rendered output.\n //\n // Hydration mode is keyed off the SSR marker script's *presence*, not off\n // the parsed payload — a parse failure would still leave server-rendered\n // markup in the DOM, and calling createRoot on it would wipe it out and\n // trigger a flash plus hydration mismatch warnings.\n const isHydrating = hasSsrMarker();\n const ssrState = readSsrState();\n if (ssrState?.session) {\n hydrateSession(ssrState.session);\n startSessionHeartbeat();\n }\n\n const container = document.getElementById('root')!;\n const routedTree = router ? router({ children: routesElement }) : routesElement;\n const tree = (\n <React.StrictMode>\n <AppProvider loadingElement={loadingElement}>\n <ModelenceQueryProvider>{routedTree}</ModelenceQueryProvider>\n </AppProvider>\n </React.StrictMode>\n );\n\n if (isHydrating) {\n ReactDOM.hydrateRoot(container, tree);\n } else {\n ReactDOM.createRoot(container).render(tree);\n }\n\n if (favicon) {\n const link = document.querySelector(\"link[rel~='icon']\") as HTMLLinkElement;\n if (!link) {\n const newLink = document.createElement('link');\n newLink.rel = 'icon';\n newLink.href = favicon;\n document.head.appendChild(newLink);\n } else {\n link.href = favicon;\n }\n }\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var s="module",i="modelence",r="0.18.0-dev.
|
|
2
|
-
export{s as a,i as b,r as c,c as d,n as e,o as f,p as g,d as h,a as i,l as j,m as k,y as l,u as m,g as n,h as o,v as p,x as q,j as r,b as s};//# sourceMappingURL=chunk-
|
|
3
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
var s="module",i="modelence",r="0.18.0-dev.5",c="The Node.js Framework for Real-Time MongoDB Apps",n="dist/index.js",o="dist/global.d.ts",p={".":"./dist/index.js","./client":"./dist/client.js","./server":"./dist/server.js","./telemetry":"./dist/telemetry.js","./mongodb":"./dist/mongo.js","./types":{types:"./dist/types.d.ts",default:"./dist/types.js"}},d=["dist","dist/bin"],a={modelence:"./dist/bin/modelence.js"},l={build:"tsup",dev:"tsup --watch",format:'prettier --write "src/**/*.{ts,tsx,js,jsx,json,css,md}"',"format:check":'prettier --check "src/**/*.{ts,tsx,js,jsx,json,css,md}"',lint:"eslint src --ext .ts,.tsx --fix","lint:check":"eslint src --ext .ts,.tsx",prepublishOnly:"npm run build",bench:"tsx src/bench/index.ts",test:"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage",postversion:"git push && git push --tags",prepare:"cd ../.. && git config core.hooksPath .husky"},m={type:"git",url:"git+https://github.com/modelence/modelence.git"},y="Modelence",u="SEE LICENSE IN LICENSE",g={url:"https://github.com/modelence/modelence/issues"},h="https://modelence.com",v={"@tanstack/react-query":"^5.100.7","@types/archiver":"^6.0.3","@types/bcrypt":"^6.0.0","@types/cookie-parser":"^1.4.9","@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","@types/socket.io":"^3.0.1","@typescript-eslint/eslint-plugin":"^8.17.0","@typescript-eslint/parser":"^8.17.0",eslint:"^9.37.0",husky:"^9.1.7","lint-staged":"^16.2.7",prettier:"^3.6.2",react:"^19.0.0","react-dom":"^19.0.0","ts-node":"^10.9.2",vitest:"^2.1.8","@vitest/coverage-v8":"^2.1.8","vite-tsconfig-paths":"^5.1.4"},x={"@socket.io/mongo-adapter":"^0.4.0","@vitejs/plugin-react":"^4.3.4",archiver:"^7.0.1",bcrypt:"^6.0.0",commander:"^12.0.0","cookie-parser":"^1.4.7",dotenv:"^16.4.5","elastic-apm-node":"^4.15.0",express:"^4.21.0","fs-extra":"^11.2.0",jiti:"^2.4.2",mongodb:"^6.8.1",open:"^10.1.0","socket.io":"^4.8.1","socket.io-client":"^4.8.1",tsup:"^8.3.6",tsx:"^4.19.3",typescript:"^5.7.2",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={"@tanstack/react-query":">=5.0.0",react:">=18.0.0","react-dom":">=18.0.0"},b={type:s,name:i,version:r,description:c,main:n,types:o,exports:p,files:d,bin:a,scripts:l,"lint-staged":{"src/**/*.{ts,tsx,js,jsx,json,css,md}":"prettier --write"},repository:m,author:y,license:u,bugs:g,homepage:h,devDependencies:v,dependencies:x,peerDependencies:j};
|
|
2
|
+
export{s as a,i as b,r as c,c as d,n as e,o as f,p as g,d as h,a as i,l as j,m as k,y as l,u as m,g as n,h as o,v as p,x as q,j as r,b as s};//# sourceMappingURL=chunk-X22U5KA3.js.map
|
|
3
|
+
//# sourceMappingURL=chunk-X22U5KA3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json"],"names":["type","name","version","description","main","types","exports","files","bin","scripts","repository","author","license","bugs","homepage","devDependencies","dependencies","peerDependencies","package_default"],"mappings":"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","file":"chunk-
|
|
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":"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","file":"chunk-X22U5KA3.js","sourcesContent":["{\n \"type\": \"module\",\n \"name\": \"modelence\",\n \"version\": \"0.18.0-dev.5\",\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 \"./telemetry\": \"./dist/telemetry.js\",\n \"./mongodb\": \"./dist/mongo.js\",\n \"./types\": {\n \"types\": \"./dist/types.d.ts\",\n \"default\": \"./dist/types.js\"\n }\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 \"format\": \"prettier --write \\\"src/**/*.{ts,tsx,js,jsx,json,css,md}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{ts,tsx,js,jsx,json,css,md}\\\"\",\n \"lint\": \"eslint src --ext .ts,.tsx --fix\",\n \"lint:check\": \"eslint src --ext .ts,.tsx\",\n \"prepublishOnly\": \"npm run build\",\n \"bench\": \"tsx src/bench/index.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"postversion\": \"git push && git push --tags\",\n \"prepare\": \"cd ../.. && git config core.hooksPath .husky\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js,jsx,json,css,md}\": \"prettier --write\"\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 \"@tanstack/react-query\": \"^5.100.7\",\n \"@types/archiver\": \"^6.0.3\",\n \"@types/bcrypt\": \"^6.0.0\",\n \"@types/cookie-parser\": \"^1.4.9\",\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 \"@types/socket.io\": \"^3.0.1\",\n \"@typescript-eslint/eslint-plugin\": \"^8.17.0\",\n \"@typescript-eslint/parser\": \"^8.17.0\",\n \"eslint\": \"^9.37.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^16.2.7\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"ts-node\": \"^10.9.2\",\n \"vitest\": \"^2.1.8\",\n \"@vitest/coverage-v8\": \"^2.1.8\",\n \"vite-tsconfig-paths\": \"^5.1.4\"\n },\n \"dependencies\": {\n \"@socket.io/mongo-adapter\": \"^0.4.0\",\n \"@vitejs/plugin-react\": \"^4.3.4\",\n \"archiver\": \"^7.0.1\",\n \"bcrypt\": \"^6.0.0\",\n \"commander\": \"^12.0.0\",\n \"cookie-parser\": \"^1.4.7\",\n \"dotenv\": \"^16.4.5\",\n \"elastic-apm-node\": \"^4.15.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 \"socket.io\": \"^4.8.1\",\n \"socket.io-client\": \"^4.8.1\",\n \"tsup\": \"^8.3.6\",\n \"tsx\": \"^4.19.3\",\n \"typescript\": \"^5.7.2\",\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 \"@tanstack/react-query\": \">=5.0.0\",\n \"react\": \">=18.0.0\",\n \"react-dom\": \">=18.0.0\"\n }\n}\n"]}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as ConfigKey, c as ConfigParams, A as AnyMethodShape, V as ValueType, d as ConfigType, O as OAuthProvider, W as WebsocketClientProvider, e as ClientChannel } from './types-
|
|
1
|
+
import { b as ConfigKey, c as ConfigParams, A as AnyMethodShape, V as ValueType, d as ConfigType, O as OAuthProvider, W as WebsocketClientProvider, e as ClientChannel } from './types-BmVlYelB.js';
|
|
2
2
|
import { ObjectId } from 'mongodb';
|
|
3
3
|
import React, { ReactNode } from 'react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{j as AppProvider,e as ClientChannel,a as createClientModule,g as deleteFile,h as downloadFile,i as getFileUrl,d as renderApp,b as systemConfig,f as uploadFile}from'./chunk-
|
|
1
|
+
export{j as AppProvider,e as ClientChannel,a as createClientModule,g as deleteFile,h as downloadFile,i as getFileUrl,d as renderApp,b as systemConfig,f as uploadFile}from'./chunk-TQI5WDPR.js';export{h as ModelenceQueryClient,m as ModelenceQueryProvider,f as connectModelenceQueryClient,l as createQueryKey,g as disconnectModelenceQueryClient,d as getWebsocketClientProvider,j as modelenceLiveQuery,k as modelenceMutation,i as modelenceQuery,c as setWebsocketClientProvider,e as startWebsockets,b as subscribeLiveQuery}from'./chunk-SABBG2XG.js';export{o as MethodError,q as callMethod,s as getConfig,a as getLocalStorageSession,j as linkOAuthProvider,c as loginWithPassword,g as logout,f as resendEmailVerification,i as resetPassword,h as sendResetPasswordToken,b as signupWithPassword,k as unlinkOAuthProvider,d as updateProfile,z as useSession,e as verifyEmail}from'./chunk-R6OOTUGO.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=client.js.map
|
|
2
2
|
//# sourceMappingURL=client.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as ConfigSchema, W as WebsocketClientProvider, a as WebsocketServerProvider } from './types-
|
|
1
|
+
export { C as ConfigSchema, W as WebsocketClientProvider, a as WebsocketServerProvider } from './types-BmVlYelB.js';
|
|
2
2
|
export { M as ModelenceConfig } from './index-pPrHYnzB.js';
|
|
3
3
|
import 'http';
|
|
4
4
|
import 'mongodb';
|
|
@@ -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-X22U5KA3.js';//# sourceMappingURL=package-U4D5AOYA.js.map
|
|
2
|
+
//# sourceMappingURL=package-U4D5AOYA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-U4D5AOYA.js"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"renderApp-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"renderApp-ZQEZU2MT.js"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export{g as getCallContext,f as startServer}from'./chunk-3XTC4WGD.js';import'./chunk-X22U5KA3.js';import'./chunk-GZI4X3CV.js';import'./chunk-C3UESBRX.js';import'./chunk-3SPXJEOR.js';import'./chunk-FL573BOT.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server-Z77W2F6P.js.map
|
|
2
|
+
//# sourceMappingURL=server-Z77W2F6P.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"server-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"server-Z77W2F6P.js"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { A as AppServer } from './index-pPrHYnzB.js';
|
|
2
|
-
import { c as ConfigParams, C as ConfigSchema, A as AnyMethodShape, S as ServerChannel, V as ValueType, f as SignupProps, U as UpdateProfileProps, g as AuthSuccessProps, h as AuthErrorProps, i as
|
|
3
|
-
export { d as ConfigType } from './types-
|
|
4
|
-
import { S as Store, R as RouteDefinition, C as CronJobInputParams, a as RateLimitRule, E as EmailProvider, b as RateLimitType, I as InferDocumentType, c as EmailPayload } from './types-
|
|
5
|
-
export { H as HttpMethod, d as RouteHandler, e as RouteParams, f as RouteResponse, s as schema } from './types-
|
|
2
|
+
import { c as ConfigParams, C as ConfigSchema, A as AnyMethodShape, S as ServerChannel, V as ValueType, f as SignupProps, U as UpdateProfileProps, g as AuthSuccessProps, h as AuthErrorProps, i as ConnectionInfo, j as User, k as OAuthErrorInfo, a as WebsocketServerProvider, R as RoleDefinition, M as MethodDefinition, b as ConfigKey, l as AppConfig, m as Session, n as UserInfo, o as Role } from './types-BmVlYelB.js';
|
|
3
|
+
export { d as ConfigType } from './types-BmVlYelB.js';
|
|
4
|
+
import { S as Store, R as RouteDefinition, C as CronJobInputParams, a as RateLimitRule, E as EmailProvider, b as RateLimitType, I as InferDocumentType, c as EmailPayload } from './types-V74rNt-g.js';
|
|
5
|
+
export { H as HttpMethod, d as RouteHandler, e as RouteParams, f as RouteResponse, s as schema } from './types-V74rNt-g.js';
|
|
6
6
|
import { ObjectId as ObjectId$1 } from 'mongodb';
|
|
7
7
|
export { ObjectId } from 'mongodb';
|
|
8
8
|
import * as zod from 'zod';
|
|
@@ -213,6 +213,23 @@ type GenerateHandleProps = {
|
|
|
213
213
|
firstName?: string;
|
|
214
214
|
lastName?: string;
|
|
215
215
|
};
|
|
216
|
+
/**
|
|
217
|
+
* Props passed to {@link AuthConfig.onBeforeSignup}.
|
|
218
|
+
*
|
|
219
|
+
* The hook fires after validation and the built-in disposable-email check,
|
|
220
|
+
* but before the user document is inserted. Throwing aborts the signup —
|
|
221
|
+
* the thrown error is re-thrown to the caller and `onSignupError` fires.
|
|
222
|
+
*/
|
|
223
|
+
type BeforeSignupProps = {
|
|
224
|
+
/** Lowercased, validated email address. */
|
|
225
|
+
email: string;
|
|
226
|
+
firstName?: string;
|
|
227
|
+
lastName?: string;
|
|
228
|
+
handle?: string;
|
|
229
|
+
/** Provider that initiated the signup. Currently only `'email'`. */
|
|
230
|
+
provider: 'email';
|
|
231
|
+
connectionInfo?: ConnectionInfo;
|
|
232
|
+
};
|
|
216
233
|
/**
|
|
217
234
|
* Callback options for authentication operations
|
|
218
235
|
*/
|
|
@@ -289,6 +306,20 @@ type AuthConfig = {
|
|
|
289
306
|
* Use for failure analytics or alerting — does NOT change the response sent to the client.
|
|
290
307
|
*/
|
|
291
308
|
onLoginError?: (props: AuthErrorProps) => void;
|
|
309
|
+
/**
|
|
310
|
+
* Hook fired after validation and the built-in disposable-email check, but
|
|
311
|
+
* before the new user document is inserted. Throwing aborts the signup —
|
|
312
|
+
* the thrown error is re-thrown to the caller and `onSignupError` fires.
|
|
313
|
+
*
|
|
314
|
+
* Use this to plug in a custom domain-policy check (e.g. a tenant-specific
|
|
315
|
+
* email-domain verification service) without having to disable the built-in
|
|
316
|
+
* disposable-email check.
|
|
317
|
+
*
|
|
318
|
+
* Currently only invoked for `'email'` provider signups. OAuth signups are
|
|
319
|
+
* not gated because OAuth providers (Google, GitHub, etc.) do not issue
|
|
320
|
+
* disposable accounts.
|
|
321
|
+
*/
|
|
322
|
+
onBeforeSignup?: (props: BeforeSignupProps) => void | Promise<void>;
|
|
292
323
|
/**
|
|
293
324
|
* Fires after a successful signup once the user record is created and the
|
|
294
325
|
* session is linked. Receives `{ provider, user, session, connectionInfo }`.
|
|
@@ -359,6 +390,18 @@ type AuthConfig = {
|
|
|
359
390
|
* full semantics and examples.
|
|
360
391
|
*/
|
|
361
392
|
rateLimits?: AuthRateLimitsConfig;
|
|
393
|
+
/**
|
|
394
|
+
* When `true`, the built-in disposable-email check is skipped during signup.
|
|
395
|
+
* Defaults to `false` (built-in check enforced).
|
|
396
|
+
*
|
|
397
|
+
* Set this to `true` when you want to enforce your own domain-policy logic
|
|
398
|
+
* via {@link onBeforeSignup} — for example, a service that classifies
|
|
399
|
+
* domains as public/disposable/custom with its own data sources and cache.
|
|
400
|
+
*
|
|
401
|
+
* Skipping the built-in check without registering an `onBeforeSignup` hook
|
|
402
|
+
* means disposable emails will be allowed to sign up.
|
|
403
|
+
*/
|
|
404
|
+
allowDisposableEmails?: boolean;
|
|
362
405
|
};
|
|
363
406
|
|
|
364
407
|
/**
|
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-3XTC4WGD.js';import'./chunk-X22U5KA3.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-GZI4X3CV.js';import'./chunk-C3UESBRX.js';export{a as getConfig}from'./chunk-3SPXJEOR.js';import'./chunk-FL573BOT.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server.js.map
|
|
2
2
|
//# sourceMappingURL=server.js.map
|
|
@@ -293,4 +293,4 @@ interface WebsocketClientProvider {
|
|
|
293
293
|
}): void;
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
export { type AnyMethodShape as A, type ConfigSchema as C, type DefaultRoles as D, type Handler as H, type MethodDefinition as M, type OAuthProvider as O, type Permission as P, type RoleDefinition as R, ServerChannel as S, type UpdateProfileProps as U, type ValueType as V, type WebsocketClientProvider as W, type WebsocketServerProvider as a, type ConfigKey as b, type ConfigParams as c, type ConfigType as d, ClientChannel as e, type SignupProps as f, type AuthSuccessProps as g, type AuthErrorProps as h, type
|
|
296
|
+
export { type AnyMethodShape as A, type ConfigSchema as C, type DefaultRoles as D, type Handler as H, type MethodDefinition as M, type OAuthProvider as O, type Permission as P, type RoleDefinition as R, ServerChannel as S, type UpdateProfileProps as U, type ValueType as V, type WebsocketClientProvider as W, type WebsocketServerProvider as a, type ConfigKey as b, type ConfigParams as c, type ConfigType as d, ClientChannel as e, type SignupProps as f, type AuthSuccessProps as g, type AuthErrorProps as h, type ConnectionInfo as i, type User as j, type OAuthErrorInfo as k, type AppConfig as l, type Session as m, type UserInfo as n, type Role as o, type Context as p, type Args as q, type AuthProvider as r, type ClientInfo as s, type Configs as t, type Method as u, type MethodType as v, SUPPORTED_OAUTH_PROVIDERS as w, type UserEmail as x };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './index-pPrHYnzB.js';
|
|
2
|
-
import {
|
|
2
|
+
import { p as Context } from './types-BmVlYelB.js';
|
|
3
3
|
import * as mongodb from 'mongodb';
|
|
4
4
|
import { WithId, IndexDescription, SearchIndexDescription, MongoClient, Collection, FilterOperators, Document, FindOptions, ObjectId, SortDirection, OptionalUnlessRequiredId, ClientSession, InsertOneResult, InsertManyResult, UpdateFilter, UpdateResult, DeleteResult, FindOneAndUpdateOptions, FindOneAndDeleteOptions, WithoutId, FindOneAndReplaceOptions, ReplaceOptions, DistinctOptions, ChangeStreamOptions, ChangeStream, AggregateOptions, AggregationCursor, AnyBulkWriteOperation, BulkWriteResult } from 'mongodb';
|
|
5
5
|
import { z, ZodNumber, ZodArray } from 'zod';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { A as AppServer, a as AppServerInitOptions, E as ExpressMiddleware, M as ModelenceConfig } from './index-pPrHYnzB.js';
|
|
2
|
-
export { A as AnyMethodShape,
|
|
3
|
-
export { B as BodyConfig, g as CronJob, C as CronJobInputParams, h as CronJobMetadata, i as EmailAttachment, c as EmailPayload, E as EmailProvider, j as ExpressHandler, H as HttpMethod, I as InferDocumentType, M as ModelSchema, a as RateLimitRule, b as RateLimitType, R as RouteDefinition, d as RouteHandler, k as RouteHandlers, e as RouteParams, f as RouteResponse, s as schema } from './types-
|
|
2
|
+
export { A as AnyMethodShape, l as AppConfig, q as Args, h as AuthErrorProps, r as AuthProvider, g as AuthSuccessProps, s as ClientInfo, b as ConfigKey, c as ConfigParams, C as ConfigSchema, d as ConfigType, t as Configs, i as ConnectionInfo, p as Context, D as DefaultRoles, H as Handler, u as Method, M as MethodDefinition, v as MethodType, k as OAuthErrorInfo, O as OAuthProvider, P as Permission, o as Role, R as RoleDefinition, w as SUPPORTED_OAUTH_PROVIDERS, m as Session, f as SignupProps, U as UpdateProfileProps, j as User, x as UserEmail, n as UserInfo, V as ValueType, W as WebsocketClientProvider, a as WebsocketServerProvider } from './types-BmVlYelB.js';
|
|
3
|
+
export { B as BodyConfig, g as CronJob, C as CronJobInputParams, h as CronJobMetadata, i as EmailAttachment, c as EmailPayload, E as EmailProvider, j as ExpressHandler, H as HttpMethod, I as InferDocumentType, M as ModelSchema, a as RateLimitRule, b as RateLimitType, R as RouteDefinition, d as RouteHandler, k as RouteHandlers, e as RouteParams, f as RouteResponse, s as schema } from './types-V74rNt-g.js';
|
|
4
4
|
import 'express';
|
|
5
5
|
import 'http';
|
|
6
6
|
import 'mongodb';
|
package/package.json
CHANGED
package/dist/chunk-TJ626QWY.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {s as s$1}from'./chunk-UMT3RHGL.js';import {a,b,c,k,l,m,n,g,h as h$1,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-GZI4X3CV.js';import {d as d$1,a as a$5}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$2,k as k$1,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}from'./chunk-FL573BOT.js';import {a as a$4,b as b$1}from'./chunk-5M6FUMUK.js';import {a as a$1}from'./chunk-DO5TZLF5.js';import _r from'dotenv';import Ho from'fs/promises';import fo from'os';import W 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 Jr from'bcrypt';import I,{z}from'zod';import {randomBytes,randomUUID}from'crypto';import {createServer,defineConfig,loadConfigFromFile,mergeConfig}from'vite';import Lo from'@vitejs/plugin-react';import qe from'fs';import U,{Router}from'express';import Ri from'cookie-parser';import Ai from'http';var Z=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 At(){if(P)return P;let e=D();if(!e)throw new Error("MongoDB URI is not set");let t=Z.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 D(){return Z.getConfig("mongodbUri")||void 0}function me(){return P}var ee=null,Fr="_modelenceSocketio",kt=60;async function Vr({httpServer:e,channels:t}){let r=me(),o=!!a$2("_system.multiInstance");console.log("Initializing Socket.IO server...");let i=null;if(o&&r){i=r.db().collection(Fr);try{await i.createIndex({createdAt:1},{expireAfterSeconds:kt,background:!0});}catch(n){if(n instanceof Error&&"code"in n&&n.code===85)try{await i.dropIndex("createdAt_1"),await i.createIndex({createdAt:1},{expireAfterSeconds:kt,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:",n);}}ee=new Server(e,{cors:{origin:"*",methods:["GET","POST"]},adapter:i?createAdapter(i):void 0,transports:["websocket"],perMessageDeflate:false}),ee.on("error",n=>{console.error("Socket.IO error:",n);}),ee.use(async(n,s)=>{let a=n.handshake.auth.token;try{n.data=await q$1(a);}finally{s();}}),ee.on("connection",n=>{n.on("disconnect",()=>{A(n);}),n.on("joinChannel",async s=>{let[a]=s.split(":"),c=false;for(let l of t)if(l.category===a){(!l.canAccessChannel||await l.canAccessChannel(n.data))&&(n.join(s),c=true,n.emit("joinedChannel",s));break}c||n.emit("joinError",{channel:s,error:"Access denied"});}),n.on("leaveChannel",s=>{n.leave(s),console.log(`User ${n.id} left channel ${s}`),n.emit("leftChannel",s);}),n.on("subscribeLiveQuery",s=>y$1(n,s)),n.on("unsubscribeLiveQuery",s=>z$1(n,s));}),console.log("Socket.IO server initialized");}function zr({category:e,id:t,data:r}){ee?.to(`${e}:${t}`).emit(e,r);}var xt={init:Vr,broadcast:zr};async function Ot(e){let t=e.toLowerCase().trim().split("@");if(t.length!==2)return false;let r=t[1];return !!await l.findOne({domain:r})}var Lt={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(n=>n.trim().toLowerCase()).filter(n=>n.length>0),o=new Date,i=500;for(let n=0;n<r.length;n+=i){let s=r.slice(n,n+i);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,$=50,_t=8,Pt=128,Mt=254,It=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(),Br=z.object({firstName:Oe({max:50}),lastName:Oe({max:50}),avatarUrl:Oe({max:400}),handle:It({min:pe,max:$})}).strict();function fe(e){let t=Br.partial().safeParse(e);if(!t.success){let r=t.error.issues[0],o=r.path.join("."),i=o?`${o}: ${r.message}`:r.message;throw new Error(i)}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 It({min:pe,max:$}).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 Tt(e){let t=e.slice(0,$);try{if(!await k.findOne({handle:t},{collation:{locale:"en",strength:2}}))return t}catch(i){throw new Error(`Database error while checking handle availability: ${i}`)}let r=51;for(let i=2;i<=r;i++){let n=`_${i}`,s=`${t.slice(0,$-n.length)}${n}`;try{if(!await k.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 i=0;i<o;i++){let n=`_${randomBytes(3).toString("hex")}`,s=`${t.slice(0,$-n.length)}${n}`;try{if(!await k.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 j(e,t,{throwOnConflict:r=true}={}){if(e!=null&&String(e).trim()!==""){let i=Ut(String(e).trim());if(r){if(await k.findOne({handle:i},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");return i}return Tt(i)}let o=t.split("@")[0].padEnd(pe,"_").slice(0,$);return Tt(o)}var Le=Object.freeze({});function Nt(e){Le=Object.freeze(Object.assign({},Le,e));}function w(){return Le}var _e=Object.freeze({});function Dt(e){_e=Object.freeze(Object.assign({},_e,e));}function y(){return _e}async function jt(e,{user:t,session:r,connectionInfo:o,res:i}){try{if(!r)throw new Error("Session is not initialized");let n=o?.ip;n&&await R({bucket:"signin",type:"ip",value:n});let s=M(e.email),a=z.string().parse(e.password),c=await k.findOne({"emails.address":s,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}}),l=c?.authMethods?.password?.hash;if(!l)throw $t();if(!c.emails?.find(b=>b.address.toLowerCase()===s)?.verified&&w()?.provider)throw new Error("Your email address hasn't been verified yet. Please check your inbox for the verification email.");if(!await Jr.compare(a,l))throw $t();return await d(r.authToken,c._id),i&&h$1(i,r.authToken),y().onAfterLogin?.({provider:"email",user:c,session:r,connectionInfo:o}),y().login?.onSuccess?.(c),{user:he(c)}}catch(n){throw n instanceof Error&&(y().onLoginError?.({provider:"email",error:n,session:r,connectionInfo:o}),y().login?.onError?.(n)),n}}async function Ht(e$1,{session:t,res:r}){if(!t)throw new Error("Session is not initialized");await e(t.authToken),r&&i(r);}function $t(){return new Error("Incorrect email/password combination")}async function Gt(e,{user:t}){if(!t)throw new Error("Not authenticated");let r=await k.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 Ft(e,{user:t}){if(!t)throw new Error("Not authenticated");let r=await k.requireById(t.id),o=fe(e);if(await y().validateProfileUpdate?.(o),"handle"in o&&o.handle!==void 0&&await k.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 i={},n={};for(let[a,c]of Object.entries(o))c===void 0?n[a]="":i[a]=c;let s={};Object.keys(i).length>0&&(s.$set=i),Object.keys(n).length>0&&(s.$unset=n);try{await k.updateOne({_id:r._id},s);let a=Object.fromEntries(Object.keys(n).map(c=>[c,void 0]));r={...r,...i,...a};}catch(a){throw a instanceof Error&&"code"in a&&a.code===11e3?new Error("Handle already taken."):a}}return {user:he(r)}}var Pe=["google","github"];async function Vt({provider:e},{user:t}){if(!t)throw new Error("You must be signed in to unlink a provider.");if(typeof e!="string"||!Pe.includes(e))throw new Error(`Invalid provider. Supported providers are: ${Pe.join(", ")}.`);let r=await k.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.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 re=new b("_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 Me=[];function zt(e){if(Me.length>0)throw new Error("Duplicate call to initRateLimits - already initialized");Me=e;}async function R(e){let{bucket:t,type:r,value:o,message:i}=e,n=Me.filter(a=>a.bucket===t&&a.type===r),s=i?()=>new d$1(i):void 0;for(let a of n)await Kr(a,o,s);}async function Kr(e,t,r){let o=()=>r?r():new d$1(`Rate limit exceeded for ${e.bucket}`),i=await re.findOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window}),n=Date.now(),s=Math.floor(n/e.window)*e.window,{count:a,modifier:c}=i?Qr(i,s,n):{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 re.upsertOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window},c);}function Qr(e,t,r){let o=t-e.windowMs;if(e.windowStart.getTime()===t){let i=e.windowCount,n=e.prevWindowCount,s=1-(r-t)/e.windowMs;return {count:Math.round(i+n*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 i=1-(r-t)/e.windowMs;return {count:Math.round(e.windowCount*i),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 Bt({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 Zr(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.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 i=await k.findOneAndUpdate({_id:t.userId,status:{$nin:["deleted","disabled"]},"emails.address":o,"emails.verified":{$ne:true}},{$set:{"emails.$.verified":true}},{returnDocument:"after"});if(!i)throw await k.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:i,email:o}}async function qt(e){let t=a$2("_system.site.url"),r=w().verification?.redirectUrl||w().emailVerifiedRedirectUrl||t||"/";try{let o=z.string().parse(e.query.token),{userDoc:i}=await Zr(o);y().onAfterEmailVerification?.({provider:"email",user:i,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(i._id);return h$1(e.res,s),{status:301,redirect:`${r}?status=verified`}}catch(o){let i=o instanceof Error?o.message:"An unexpected error occurred";return o instanceof Error&&(y().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(i)}`}}}async function Ue({userId:e,email:t,baseUrl:r=a$2("_system.site.url")}){if(w().provider){let o=w().provider,i=randomBytes(32).toString("hex"),n=new Date(Date.now()+a$1.hours(24));await m.insertOne({userId:e,email:t,token:i,createdAt:new Date,expiresAt:n});let s$1=`${r}/api/_internal/auth/verify-email?token=${i}`,c=(w()?.verification?.template||Bt)({name:"",email:t,verificationUrl:s$1}),l=s(c);await o?.sendEmail({to:t,from:w()?.from||"noreply@modelence.com",subject:w()?.verification?.subject||"Verify your email address",text:l,html:c});}}var Ie={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function Jt(e,{connectionInfo:t}){let r=M(e.email),o=await k.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!o)return Ie;let i=o.emails?.find(n=>n.address.toLowerCase()===r);if(!i||i.verified)return Ie;if(!w().provider)throw new Error("Email provider is not configured");return await R({bucket:"verification",type:"user",value:o._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await Ue({userId:o._id,email:r,baseUrl:t?.baseUrl}),Ie}async function Wt(e,{user:t,session:r,connectionInfo:o}){let i=y();try{let n=e,{firstName:s,lastName:a,avatarUrl:c,handle:l}=n,d=M(n.email),p=ge(n.password),b=o?.ip;if(b&&await R({bucket:"signupAttempt",type:"ip",value:b}),await Ot(d))throw new Error("Please use a permanent email address");let S=await k.findOne({"emails.address":d},{collation:{locale:"en",strength:2}});if(S){let O=S.emails?.find(Ae=>Ae.address.toLowerCase()===d);throw S.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: ${O?.address}`)}b&&await R({bucket:"signup",type:"ip",value:b});let E=fe({firstName:s,lastName:a,avatarUrl:c,handle:l});await i.validateSignup?.({email:d,password:p,...E});let A;if(E.handle)A=await j(E.handle,d);else if(i.generateHandle){let O=await i.generateHandle({email:d,firstName:E.firstName,lastName:E.lastName});A=await j(O,d,{throwOnConflict:!1});}else A=await j(void 0,d);let Re=await Jr.hash(p,10),T=await k.insertOne({handle:A,status:"active",emails:[{address:d,verified:!1}],createdAt:new Date,authMethods:{password:{hash:Re}},...E.firstName!==void 0&&{firstName:E.firstName},...E.lastName!==void 0&&{lastName:E.lastName},...E.avatarUrl!==void 0&&{avatarUrl:E.avatarUrl}}),ae=await k.findOne({_id:T.insertedId},{readPreference:"primary"});if(!ae)throw new Error("User not found");return await Ue({userId:T?.insertedId,email:d,baseUrl:o?.baseUrl}),i.onAfterSignup?.({provider:"email",user:ae,session:r,connectionInfo:o}),i.signup?.onSuccess?.(ae),T.insertedId}catch(n){throw n instanceof Error&&(i.onSignupError?.({provider:"email",error:n,session:r,connectionInfo:o}),i.signup?.onError?.(n)),n}}function io(e,t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`${e}${t.startsWith("/")?"":"/"}${t}`:e}function no({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 Te={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function Kt(e,{connectionInfo:t}){let r=M(e.email),o=t?.ip;o&&await R({bucket:"passwordReset",type:"ip",value:o}),await R({bucket:"passwordReset",type:"email",value:r});let i=await k.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!i||!i.authMethods?.password)return Te;let n$1=w().provider;if(!n$1)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:i._id,email:r,token:s$1,createdAt:c,expiresAt:l});let d=a$2("_system.site.url")||t?.baseUrl,b=`${io(d,w().passwordReset?.redirectUrl)}?token=${s$1}`,E=(w()?.passwordReset?.template||no)({email:r,resetUrl:b,name:""}),A=s(E);return await n$1.sendEmail({to:r,from:w()?.from||"noreply@modelence.com",subject:w()?.passwordReset?.subject||"Reset your password",text:A,html:E}),Te}async function Qt(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 i=await k.findOne({_id:o.userId});if(!i)throw new Error("User not found");let n$1=await Jr.hash(r,10);return await k.updateOne({_id:i._id},{$set:{"authMethods.password.hash":n$1}}),o.email&&await k.updateOne({_id:i._id,"emails.address":o.email},{$set:{"emails.$.verified":true}}),await f(i._id),await n.deleteOne({token:t}),{success:true,message:"Password has been reset successfully"}}var Yt=false;function so(e){Yt||(Yt=true,console.warn(`[modelence] auth.rateLimits.${e}: the legacy object form (e.g. { perIp15Minutes, perIpPerDay }) is deprecated and will be removed in 1.0.0. Use the array form: [{ type: 'ip', window: time.minutes(15), limit: 10 }, ...].`));}function Xt(e){return `${e.bucket}\0${e.type}\0${e.window}`}function ao(){return [{bucket:"signup",type:"ip",window:a$1.minutes(15),limit:20},{bucket:"signup",type:"ip",window:a$1.days(1),limit:200},{bucket:"signupAttempt",type:"ip",window:a$1.minutes(15),limit:50},{bucket:"signupAttempt",type:"ip",window:a$1.days(1),limit:500},{bucket:"signin",type:"ip",window:a$1.minutes(15),limit:50},{bucket:"signin",type:"ip",window:a$1.days(1),limit:500},{bucket:"verification",type:"user",window:a$1.seconds(60),limit:1},{bucket:"verification",type:"user",window:a$1.days(1),limit:10},{bucket:"passwordReset",type:"ip",window:a$1.minutes(15),limit:10},{bucket:"passwordReset",type:"ip",window:a$1.days(1),limit:100},{bucket:"passwordReset",type:"email",window:a$1.hours(1),limit:5},{bucket:"passwordReset",type:"email",window:a$1.days(1),limit:10}]}function co(e,t){let r=[];if(e==="verification"){let i=t;return i.perUserPerMinute!==void 0&&r.push({bucket:e,type:"user",window:a$1.seconds(60),limit:i.perUserPerMinute}),i.perUserPerDay!==void 0&&r.push({bucket:e,type:"user",window:a$1.days(1),limit:i.perUserPerDay}),r}let o=t;if(o.perIp15Minutes!==void 0&&r.push({bucket:e,type:"ip",window:a$1.minutes(15),limit:o.perIp15Minutes}),o.perIpPerDay!==void 0&&r.push({bucket:e,type:"ip",window:a$1.days(1),limit:o.perIpPerDay}),e==="passwordReset"){let i=t;i.perEmailPerHour!==void 0&&r.push({bucket:e,type:"email",window:a$1.hours(1),limit:i.perEmailPerHour}),i.perEmailPerDay!==void 0&&r.push({bucket:e,type:"email",window:a$1.days(1),limit:i.perEmailPerDay});}return r}function lo(e){let t=[],r=["signup","signupAttempt","signin","verification","passwordReset"];for(let o of r){let i=e[o];if(i!==void 0)if(Array.isArray(i))for(let n of i)t.push({bucket:o,...n});else {so(o);for(let n of co(o,i))t.push(n);}}return t}function Ne(e={}){let t=ao(),r=lo(e),o=new Map;for(let s of r)o.set(Xt(s),s);let i=[],n=new Set;for(let s of t){let a=Xt(s),c=o.get(a);c!==void 0?(i.push(c),n.add(a)):i.push(s);}for(let[s,a]of o)n.has(s)||i.push(a);return i}var De=new a("_system.user",{stores:[k,l,m,n],queries:{getOwnProfile:Gt},mutations:{signupWithPassword:Wt,loginWithPassword:jt,logout:Ht,resendEmailVerification:Jt,sendResetPasswordToken:Kt,resetPassword:Qt,updateProfile:Ft,unlinkOAuthProvider:Vt},cronJobs:{updateDisposableEmailList:Lt},rateLimits:Ne(),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 uo={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 mo(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 po(e,t){let r=[];for(let[o,i]of Object.entries(e)){let n=process.env[o],s=t[i];if(n){let a=s?.type??"string";r.push({key:i,type:a,value:mo(n,a)});}}return r}function we(e,t="withoutRemoteServer"){let r=uo[t];return po(r,e)}async function Zt({configSchema:e,cronJobsMetadata:t,stores:r,roles:o}){let i=process.env.MODELENCE_CONTAINER_ID;if(!i)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");try{let n=(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:fo.hostname(),containerId:i,dataModels:n,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(n){throw console.error("Unable to connect to Modelence Cloud:",n),n}}async function er(){return $e("/api/configs","GET")}async function tr(){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:i,MODELENCE_SERVICE_TOKEN:n}=process.env;if(!i)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set");let s=await fetch(`${i}${e}`,{method:t,headers:{Authorization:`Bearer ${n}`,...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,go=a$1.seconds(10);function rr(){setInterval(async()=>{if(!je){je=true;try{await tr();}catch(e){console.error("Error syncing status",e);}try{await ho();}catch(e){console.error("Error syncing config",e);}je=false;}},go);}function He(e){c$1(e),c$1(we(d$2(),"withRemoteServer"));}async function ho(){let{configs:e}=await er();He(e);}var H=new b("_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 G={},or=a$1.seconds(10),ar=randomBytes(32).toString("base64url"),bo=a$1.seconds(30),J=new Map,Ge=e=>e instanceof MongoError&&e.code===11e3,ir=(e,t)=>typeof e.keyPattern=="object"&&e.keyPattern!==null&&Object.prototype.hasOwnProperty.call(e.keyPattern,t),Eo=async({error:e,resource:t})=>{if(ir(e,"resource"))return true;if(ir(e,"_id"))return false;let r=await H.findOne({resource:t});return !!r&&r._id!==t},nr=async({resource:e,staleThresholdDate:t,instanceId:r})=>{let o=await H.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},cr=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 H.deleteOne(o)).deletedCount>0},vo=e=>{let t=e,r=J.get(t);r&&(r.stopRequested=true,r.timer&&(clearTimeout(r.timer),r.timer=null),J.delete(t));},sr=({resource:e,lockDuration:t,instanceId:r})=>{let o=Math.floor(t/3),i=e,n=J.get(i);if(n&&!n.stopRequested&&n.heartbeatInterval===o&&n.lockDuration===t)return;n&&(n.stopRequested=true,n.timer&&(clearTimeout(n.timer),n.timer=null),J.delete(i));let s={timer:null,stopRequested:false,lockDuration:t,heartbeatInterval:o},a=()=>{s.timer=setTimeout(()=>{F(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){J.delete(i);return}a();});},o);};J.set(i,s),a();};async function F(e,{lockDuration:t=bo,successfulLockCacheDuration:r=or,failedLockCacheDuration:o=or,heartbeat:i,bypassCache:n,instanceId:s=ar}={}){let a=Date.now();if(!n&&G[e]&&a<G[e].expiresAt)return G[e].value&&i&&sr({resource:e,lockDuration:t,instanceId:s}),G[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 Co({resource:e,staleThresholdDate:c,instanceId:s});return G[e]={value:l,expiresAt:a+(l?r:o)},l?(i&&sr({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 G[e]={value:false,expiresAt:a+o},i$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),false}}var Co=async({resource:e,staleThresholdDate:t,instanceId:r})=>{try{return await nr({resource:e,staleThresholdDate:t,instanceId:r})}catch(o){if(Ge(o)&&await Eo({error:o,resource:e})){if(!await cr({resource:e,staleThresholdDate:t,instanceId:r}))return false;try{return await nr({resource:e,staleThresholdDate:t,instanceId:r})}catch(n){if(Ge(n))return false;throw n}}if(Ge(o))return false;throw o}};async function oe(e,{instanceId:t=ar}={}){vo(e);try{let r=await H.deleteOne({_id:e,instanceId:t});return r.deletedCount===0?await cr({resource:e,instanceId:t}):r.deletedCount>0}catch{return false}finally{delete G[e];}}var V={},Fe=null,Ve=new b("_modelenceCronJobs",{schema:{alias:c.string(),lastStartDate:c.date().optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function dr(e,{description:t="",interval:r,timeout:o=Math.min(Math.max(r,a$1.minutes(1)),a$1.days(1)),handler:i}){if(V[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}]`);V[e]={alias:e,params:{description:t,interval:r,timeout:o},handler:i,state:{isRunning:false}};}async function ur(){if(Fe)throw new Error("Cron jobs already started");let e=Object.keys(V);if(e.length>0){let t={alias:{$in:e}},r=await Ve.fetch(t),o=Date.now();r.forEach(i=>{let n=V[i.alias];n&&(n.state.scheduledRunTs=i.lastStartDate?i.lastStartDate.getTime()+n.params.interval:o);}),Object.values(V).forEach(i=>{i.state.scheduledRunTs||(i.state.scheduledRunTs=o);}),Fe=setInterval(So,a$1.seconds(1));}}async function So(){let e=Date.now();await F("cron",{successfulLockCacheDuration:a$1.seconds(10),failedLockCacheDuration:a$1.seconds(30)})&&Object.values(V).forEach(async r=>{let{params:o,state:i}=r;if(i.isRunning){i.startTs&&i.startTs+o.timeout<e&&(i.isRunning=false);return}i.scheduledRunTs&&i.scheduledRunTs<=e&&await Ro(r);});}async function Ro(e){let{alias:t,params:r,handler:o,state:i}=e;i.isRunning=true,i.startTs=Date.now(),await Ve.updateOne({alias:t},{$set:{lastStartDate:new Date(i.startTs)}});let n=l$1("cron",`cron:${t}`);try{await o(),lr(i,r),n.end("success");}catch(s){lr(i,r);let a=s instanceof Error?s:new Error(String(s));m$1(a),n.end("error"),console.error(`Error in cron job '${t}':`,s);}}function lr(e,t){e.scheduledRunTs=e.startTs?e.startTs+t.interval:Date.now(),e.startTs=void 0,e.isRunning=false;}function mr(){return Object.values(V).map(({alias:e,params:t})=>({alias:e,description:t.description,interval:t.interval,timeout:t.timeout}))}var pr=new a("_system.cron",{stores:[Ve]});function fr(e){let t=[...new Set(e)],r=new Map;for(let n of t){let s=n.getChainRoot();r.set(s,s.getChainTail());}let o=[...new Set(r.values())],i=new Map;for(let[n,s]of r){let a=s.getName(),c=i.get(a);if(c!==void 0&&c!==n)throw new Error(`Store collision: multiple unrelated stores use collection name '${a}'. Use .extend() to create a single extension chain instead of independent stores.`);i.set(a,n);}return {storesToInit:t,effectiveStores:o}}var ze=new a("_system.lock",{stores:[H]});var ie=new b("_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 Be(e,{lockMode:t="acquire"}={}){if(e.length!==0){if(t==="acquire"&&!await F("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}}),i=new Set(o.map(({version:s})=>s)),n=e.filter(({version:s})=>!i.has(s));if(n.length===0)return;j$2(`Running migrations (${n.length})...`,{source:"migrations"});for(let{version:s,description:a,handler:c}of n){j$2(`Running migration v${s}: ${a}`,{source:"migrations"});try{let d=(await c()||"").toString().trim(),p=15*1024*1024,b=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:b,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 oe("migrations");}}}function gr(e){setTimeout(()=>{Be(e).catch(t=>{console.error("Error running migrations:",t);});},0);}var hr=new a("_system.migration",{stores:[ie]});var wr=new a("_system.rateLimit",{stores:[re]});async function yr({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 br(e){await q("/api/files/delete","POST",JSON.stringify({filePath:e}),{"Content-Type":"application/json"});}async function Er(e){return await q("/api/files/download","POST",JSON.stringify({filePath:e}),{"Content-Type":"application/json"})}async function vr(e){return await q("/api/files/url","POST",JSON.stringify({filePath:e}),{"Content-Type":"application/json"})}var Cr=new a("_system.files",{queries:{async downloadFile({filePath:e}){return Er(e)},async getFileUrl({filePath:e}){return vr(e)}},mutations:{async getUploadUrl({filePath:e,contentType:t,visibility:r}){return yr({filePath:e,contentType:t,visibility:r})},async deleteFile({filePath:e}){return br(e)}}});var ne="./.modelence/build/client".replace(/\\/g,"/"),_o="./.modelence/build/ssr".replace(/\\/g,"/"),Rr="/index.tsx",kr=/<div id="root">\s*<\/div>/,Po="</head>",Je=class{constructor(){this.ssrEnabled=false;this.ssrTransportInstalled=false;this.prodEntryLoaded=false;}enableSsr(){this.ssrEnabled=true;}async init({httpServer:t}){if(this.config=await $o(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-ZSBKZIXH.js');r(),this.ssrTransportInstalled=true;}}middlewares(){if(this.isDev())return this.viteServer?.middlewares??[];let t=this.ssrEnabled?{index:false}:void 0,r=[U.static(ne,t)];return this.config?.publicDir&&r.push(U.static(this.config.publicDir,t)),r}async handler(t,r){if(this.ssrEnabled&&Mo(t)){try{await this.handleSsr(t,r);}catch(o){if(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}),r.headersSent){r.end();return}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),i=await this.captureSsrSnapshot();if(!i)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[{renderSsrTreeStream:n},{getCallContext:s},a]=await Promise.all([import('./render-DLVPZOA6.js'),import('./server-GALICT5J.js'),import('./collectCss-4V7I3QV3.js')]),c=await s(t,r),l=this.collectCssAssets(a);To(r,a.buildEarlyHintsLink(l));let{sessionState:d,pipe:p,getQueryState:b}=await n({callContext:c,loadingElement:i.loadingElement,routesElement:i.routesElement,router:i.router,location:t.originalUrl});if(!kr.test(o))throw new Error('SSR template is missing the expected `<div id="root"></div>` placeholder.');let[S,E]=Io(o),A=Uo(S,a.renderStylesheetLinks(l));r.setHeader("Content-Type","text/html; charset=utf-8"),r.setHeader("Cache-Control","no-store"),r.status(200),r.write(A),r.write(`<script id="__MODELENCE_STATE__" type="application/json">${Ar(d)}</script>`),r.write('<div id="root">'),await p(r),r.write("</div>"),r.write(`<script id="__MODELENCE_QUERY_STATE__" type="application/json">${Ar(b())}</script>`),r.end(E);}collectCssAssets(t){return this.isDev()?this.viteServer?t.collectDevCssAssets(this.viteServer,Rr):{hrefs:[],source:"dev"}:(this.prodCssAssetsCache||(this.prodCssAssetsCache=t.loadProdCssAssets(ne)),this.prodCssAssetsCache)}async getTemplate(t){if(this.isDev()){let r=W.resolve(process.cwd(),"src/client/index.html"),o=qe.readFileSync(r,"utf-8");return this.viteServer&&(o=await this.viteServer.transformIndexHtml(t,o)),o}if(!this.prodTemplateCache){let r=W.resolve(process.cwd(),ne,"index.html");this.prodTemplateCache=qe.readFileSync(r,"utf-8");}return this.prodTemplateCache}async captureSsrSnapshot(){let{_getSsrSnapshot:t}=await import('./renderApp-KKWGQKMM.js');if(this.isDev()){if(!this.viteServer)throw new Error("Vite dev server not initialized");return await this.viteServer.ssrLoadModule(Rr),t()}return this.prodEntryLoaded||(await import(W.resolve(process.cwd(),_o,"index.mjs")),this.prodEntryLoaded=true),t()}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:ne});}isDev(){return process.env.NODE_ENV!=="production"}};function Mo(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()??"",i=o.lastIndexOf(".");if(i>0){let n=o.slice(i).toLowerCase();if(n!==".html"&&n!==".htm")return false}return true}function Ar(e){return e.replace(/[<>&\u2028\u2029]/g,t=>`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`)}function Io(e){let t=e.match(kr);if(!t||t.index===void 0)throw new Error('SSR template is missing the expected `<div id="root"></div>` placeholder.');let r=e.slice(0,t.index),o=e.slice(t.index+t[0].length);return [r,o]}function Uo(e,t){if(!t)return e;let r=e.lastIndexOf(Po);return r===-1?t+e:e.slice(0,r)+t+e.slice(r)}function To(e,t){if(t.length===0)return;let r=e;if(typeof r.writeEarlyHints=="function")try{r.writeEarlyHints({link:t});}catch(o){process.env.NODE_ENV!=="production"&&console.warn("Modelence SSR: writeEarlyHints failed",o);}}async function No(){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 Do(e,t){let r=mergeConfig(e,t);if(r.plugins&&Array.isArray(r.plugins)){let o=new Set;r.plugins=r.plugins.flat().filter(i=>{if(!i||typeof i!="object"||Array.isArray(i))return true;let n=i.name;return !n||o.has(n)?false:(o.add(n),true)}).reverse(),r.plugins.reverse();}return r}async function $o(e,t={}){let r=process.cwd(),o=await No(),i=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(a=>qe.existsSync(W.join(r,a))),n=[Lo(),jo()];if(i){let a=(await import('vite-plugin-eslint')).default;n.push(a({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:r,overrideConfigFile:W.resolve(r,i)}));}let s=defineConfig({plugins:n,build:{outDir:ne,emptyOutDir:true},server:{middlewareMode:true,hmr:e?{server:e}:void 0},appType:t.ssr?"custom":"spa",root:"./src/client",resolve:{alias:{"@":W.resolve(r,"src").replace(/\\/g,"/")}}});return Do(s,o)}function jo(){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 ye=new Je;var We=Object.freeze({});function xr(e){We=Object.freeze(Object.assign({},We,e));}function Or(){return We}var Ke=Object.freeze({});function Lr(e){Ke=Object.freeze(Object.assign({},Ke,e));}function be(){return Ke}async function Vo({modules:e=[],roles:t={},defaultRoles:r={},server:o$1=ye,migrations:i=[],email:n={},auth:s={},security:a={},websocket:c={}}){_r.config(),_r.config({path:".modelence.env"});let l=!!process.env.MODELENCE_SERVICE_ENDPOINT;ei().then(()=>{}).catch(()=>{});let d=[De,j$1,pr,hr,wr,Z,ze,Cr],p=[...d,...e];f$1(),Bo(d),zo(e),o(t,r);let b=Yo(p);e$1(b);let S=qo(p),E=Jo(p);Xo(p),De.rateLimits=Ne(s.rateLimits);let A=Wo(p);zt(A);let{storesToInit:Re,effectiveStores:T}=fr(S);if(l){let{configs:O,environmentId:Ae,appAlias:Nr,environmentAlias:Dr,telemetry:$r}=await Zt({configSchema:b,cronJobsMetadata:mr(),stores:T,roles:t});He(O),g$1({environmentId:Ae,appAlias:Nr,environmentAlias:Dr,telemetry:$r});}else c$1(we(b));if(Nt(n),Dt(s),xr(a),Lr({...c,provider:c.provider||xt}),D()){await At();let O=[...new Set([...Re,...T])];Zo(O),await Qo(T,i);}else gr(i);l&&(await h$2(),rr()),ur().catch(console.error),o$1===ye&&(await a$3().catch(()=>null))?.ssr&&ye.enableSsr(),await Pr(o$1,{combinedModules:p,channels:E});}function zo(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 Bo(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 qo(e){return e.flatMap(t=>t.stores)}function Jo(e){return e.flatMap(t=>t.channels)}function Wo(e){return e.flatMap(t=>t.rateLimits)}function Ko(e,t){console.warn(`Failed to create indexes for store '${e}'. Continuing startup.`,t);}var Qe="migrations";async function Qo(e,t){if(!await F(Qe,{lockDuration:a$1.seconds(30),heartbeat:true}))return;let o,i;try{o=e.filter(a=>a.getIndexCreationMode()==="blocking"),i=e.filter(a=>a.getIndexCreationMode()==="background");for(let a of o)await Ye(a,"full");for(let a of i)await Ye(a,"drop-only");}catch(a){throw await oe(Qe),a}let n=(async()=>{for(let a of i)await Ye(a,"create-only");})(),s=Be(t,{lockMode:"skip"});Promise.allSettled([n,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 oe(Qe);});}async function Ye(e,t="full"){let r=e.getName();try{await e.createIndexes(t);}catch(o){Ko(r,o);}}function Yo(e){let t={};for(let r of e)for(let[o,i]of Object.entries(r.configSchema)){let n=`${r.name}.${o}`;if(n in t)throw new Error(`Duplicate config schema key: ${n} (${r.name})`);t[n]=i;}return t}function Xo(e){for(let t of e)for(let[r,o]of Object.entries(t.cronJobs))dr(`${t.name}.${r}`,o);}function Zo(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 ei(){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 ti(),i=await import('./package-VG7P4LRW.js');await fetch(`${t}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:o.name,version:i.default.version,localHostname:fo.hostname(),environmentId:r})});}}async function ti(){try{let e=W.join(process.cwd(),"package.json"),t=await Ho.readFile(e,"utf-8");return {name:JSON.parse(t).name||"unknown"}}catch{return {name:"unknown"}}}async function Mr(e){await m.deleteMany({userId:e}),await n.deleteMany({userId:e});}async function oi(e){await Mr(e),await k.updateOne(e,{$set:{status:"disabled",disabledAt:new Date}});}async function ii(e){await Mr(e),await k.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=be().provider;if(!o){k$1("Websockets provider should be added to startApp",{});return}o.broadcast({category:this.category,id:t,data:r});}};function ni(e){if(!w().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return w().provider?.sendEmail(e)}function h(e,t,r){let o=y(),i=e.status(t);if(o.errorComponent)try{let n=o.errorComponent({error:r,statusCode:t});if(n)return i.send(n)}catch(n){console.error("Unhandled error in authConfig.errorComponent:",n);}return i.json({error:r})}async function Ze(e,t){let{authToken:r}=await g(t);h$1(e,r),e.status(302),e.redirect("/");}async function ai(e,t,r,o,i){let n=y();try{if(r.status==="disabled"||r.status==="deleted"){h(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.updateOne({_id:r._id},{$set:s}),a={...r,...s}),await Ze(e,r._id),n.onAfterLogin?.({provider:t.providerName,user:a,session:o,connectionInfo:i}),n.login?.onSuccess?.(a);}catch(s){throw s instanceof Error&&(n.login?.onError?.(s),n.onLoginError?.({provider:t.providerName,error:s,session:o,connectionInfo:i})),s}}async function ci(e,t,r,o,i){let n=y();if((n.oauthAccountLinking??"manual")==="auto"&&t.emailVerified){if(r.status==="disabled"||r.status==="deleted"){h(e,400,"User account is not active.");return}if(!r.emails?.find(c=>c.address.toLowerCase()===t.email.toLowerCase())?.verified){h(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.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)){h(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}}};n.onAfterLogin?.({provider:t.providerName,user:p,session:o,connectionInfo:i}),n.login?.onSuccess?.(p);return}catch(c){throw c instanceof Error&&(n.login?.onError?.(c),n.onLoginError?.({provider:t.providerName,error:c,session:o,connectionInfo:i})),c}}h(e,400,"User with this email already exists. Please log in instead.");}async function li(e,t,r,o){let i=y();try{let n;if(i.generateHandle){let l=await i.generateHandle({email:t.email,firstName:t.firstName,lastName:t.lastName});n=await j(l,t.email,{throwOnConflict:!1});}else n=await j(void 0,t.email);let s={handle:n,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.insertOne(s);await Ze(e,a.insertedId);let c=await k.findOne({_id:a.insertedId},{readPreference:"primary"});c&&(i.onAfterSignup?.({provider:t.providerName,user:c,session:r,connectionInfo:o}),i.signup?.onSuccess?.(c));}catch(n){throw n instanceof Error&&(i.onSignupError?.({provider:t.providerName,error:n,session:r,connectionInfo:o}),i.signup?.onError?.(n)),n}}function Q(e){return `${a$2("_system.site.url")}/api/_internal/auth/${e}/callback`}async function Ee(e,t,r){let o=await k.findOne({[`authMethods.${r.providerName}.id`]:r.id}),{session:i,connectionInfo:n}=await se(e,t);if(o)return ai(t,r,o,i,n);if(!r.email){h(t,400,`Email address is required for ${r.providerName} authentication.`);return}let s;try{s=await k.findOne({"emails.address":r.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(a){if(a instanceof Error){let c=y();c.onSignupError?.({provider:r.providerName,error:a,session:i,connectionInfo:n}),c.signup?.onError?.(a);}throw a}return s?ci(t,r,s,i,n):li(t,r,i,n)}function C(e){e.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function K(e){if(e)try{e();}catch(t){console.error("Error executing OAuth hook:",t);}}function ve(e,t,r){let o=e.query.state,i=e.cookies[r],[n,s]=(i||"").split(":");return !o||!i||o!==n?(h(t,400,"Invalid OAuth state - possible CSRF attack"),null):(t.clearCookie(r),s||"login")}async function Ce(e,t,r){let o=y(),{session:i,connectionInfo:n}=await se(e,t);if(!i?.userId){C(t),h(t,401,"You must be signed in to link a provider.");return}let s=i.userId;try{let a=`authMethods.${r.providerName}.id`;if((await k.updateOne({_id:s,status:{$nin:["deleted","disabled"]},$or:[{[a]:{$exists:!1}},{[a]:r.id}]},{$set:{[a]:r.id}})).matchedCount===0){let d=await k.findOne({_id:s});if(!d||d.status==="deleted"||d.status==="disabled"){K(()=>o.onOAuthLinkError?.({provider:r.providerName,error:new Error("User account not found or not active"),session:i,connectionInfo:n})),C(t),h(t,400,"User account is not active.");return}let p=d?.authMethods?.[r.providerName]?.id;if(p&&p!==r.id){K(()=>o.onOAuthLinkError?.({provider:r.providerName,error:new Error(`User already has a different ${r.providerName} account linked`),session:i,connectionInfo:n})),C(t),h(t,400,`You have already linked a different ${r.providerName} account.`);return}K(()=>o.onOAuthLinkError?.({provider:r.providerName,error:new Error(`Unexpected OAuth linking state for ${r.providerName}`),session:i,connectionInfo:n})),C(t),h(t,400,`Unable to link ${r.providerName} account.`);return}let l=await k.findOne({_id:s},{readPreference:"primary"});l&&K(()=>o.onAfterOAuthLink?.({provider:r.providerName,user:l,session:i,connectionInfo:n})),C(t),t.status(302).redirect("/");}catch(a){if(a instanceof MongoServerError&&a.code===11e3){K(()=>o.onOAuthLinkError?.({provider:r.providerName,error:a,session:i,connectionInfo:n})),C(t),h(t,400,`This ${r.providerName} account is already linked to a different user.`);return}if(a instanceof Error&&K(()=>o.onOAuthLinkError?.({provider:r.providerName,error:a,session:i,connectionInfo:n})),C(t),!t.headersSent)throw a}}function Se(e){return !e||typeof e!="string"?null:e}async function mi(e,t,r,o){let i=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(!i.ok)throw new Error(`Failed to exchange code for token: ${i.statusText}`);return i.json()}async function pi(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 fi(e,t){let r=Se(e.query.code);if(!r){h(t,400,"Missing authorization code");return}let o=ve(e,t,"authStateGoogle");if(!o)return;let i=String(a$2("_system.user.auth.google.clientId")),n=String(a$2("_system.user.auth.google.clientSecret")),s=Q("google");try{let a=await mi(r,i,n,s),c=await pi(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 Ce(e,t,l):await Ee(e,t,l);}catch(a){console.error("Google OAuth error:",a),o==="link"&&C(t),h(t,500,"Authentication failed");}}function gi(){let e=Router(),t=(r,o,i)=>{let n=!!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(!n||!s||!a){h(o,503,"Google authentication is not configured");return}i();};return e.get("/api/_internal/auth/google",t,(r,o)=>{let i=String(a$2("_system.user.auth.google.clientId")),n=Q("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",i),c.searchParams.append("redirect_uri",n),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,fi),e}var Ir=gi;async function yi(e,t,r,o){let i=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(!i.ok)throw new Error(`Failed to exchange code for token: ${i.statusText}`);return i.json()}async function bi(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 Ei(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 vi(e,t){return e.email?e.email:(await Ei(t)).find(o=>o.primary&&o.verified)?.email??null}async function Ci(e,t){let r=Se(e.query.code);if(!r){h(t,400,"Missing authorization code");return}let o=ve(e,t,"authStateGithub");if(!o)return;let i=String(a$2("_system.user.auth.github.clientId")),n=String(a$2("_system.user.auth.github.clientSecret")),s=Q("github");try{let a=await yi(r,i,n,s),c=await bi(a.access_token),l=await vi(c,a.access_token);if(!l){o==="link"&&C(t),h(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,b=d.length>1?d.slice(1).join(" "):void 0,S={id:String(c.id),email:l,emailVerified:!0,providerName:"github",firstName:p,lastName:b,avatarUrl:c.avatar_url||void 0};o==="link"?await Ce(e,t,S):await Ee(e,t,S);}catch(a){console.error("GitHub OAuth error:",a),o==="link"&&C(t),h(t,500,"Authentication failed");}}function Si(){let e=Router(),t=(r,o,i)=>{let n=!!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(!n||!s||!a){h(o,503,"GitHub authentication is not configured");return}i();};return e.get("/api/_internal/auth/github",t,(r,o)=>{let i=String(a$2("_system.user.auth.github.clientId")),n=Q("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",i),d.searchParams.append("redirect_uri",n),d.searchParams.append("scope",a),d.searchParams.append("state",c),o.redirect(d.toString());}),e.get("/api/_internal/auth/github/callback",t,Ci),e}var Ur=Si;function Tr(e,t,r){return async(o,i,n)=>{let s=o.headers["x-modelence-auth-token"],a={session:null,user:null};if(typeof s=="string"&&D())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:i,next:n},a);c.end(),l&&(i.status(l.status||200),l.redirect&&i.redirect(l.redirect),l.headers&&Object.entries(l.headers).forEach(([d,p])=>{i.setHeader(d,p);}),i.send(l.data));}catch(l){c.end("error"),l instanceof a$5?i.status(l.status).send(l.message):(console.error(`Error in route handler: ${o.path}`),console.error(l),i.status(500).send(String(l)));}}}function ki(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 xi(e,t){for(let r of t)for(let o of r.routes){let{path:i,handlers:n,body:s}=o,a=ki(s);Object.entries(n).forEach(([c,l])=>{e[c](i,...a,Tr(c,i,l));});}}async function Pr(e,{combinedModules:t,channels:r}){let o=U();o.use(Ri()),o.use(_i()),xi(o,t),o.use(U.json({limit:"16mb"})),o.use(U.urlencoded({extended:true,limit:"16mb"})),o.use(Ir()),o.use(Ur()),o.post("/api/_internal/auth/set-link-cookie",async(a,c)=>{let{session:l}=await se(a,c);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 l=a.params.methodName,d=await se(a,c);try{let p=a$4(await x(l,a.body.args,d));c.json({data:p,typeMap:b$1(p)});}catch(p){Oi(c,l,p);}});let i=Ai.createServer(o);await e.init({httpServer:i}),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 n=be()?.provider;n&&n.init({httpServer:i,channels:r});let s=process.env.MODELENCE_PORT||process.env.PORT||3e3;i.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"),i=e.body??{},n=I.string().nullish().transform(l=>l??null).parse(e.cookies.authToken||(o?e.cookies.oauthLinkToken:null)||i.authToken),s=I.object({screenWidth:I.number(),screenHeight:I.number(),windowWidth:I.number(),windowHeight:I.number(),pixelRatio:I.number(),orientation:I.string().nullable()}).nullish().parse(i.clientInfo)??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},a={ip:Pi(e),userAgent:e.get("user-agent"),acceptLanguage:e.get("accept-language"),referrer:e.get("referrer"),baseUrl:e.protocol+"://"+e.get("host")};if(!!D()){let{session:l,user:d,roles:p}=await q$1(n);return {clientInfo:s,connectionInfo:a,session:l,user:d,roles:p,req:e,res:t}}return {clientInfo:s,connectionInfo:a,session:null,user:null,roles:p(),req:e,res:t}}function Oi(e,t,r){if(r instanceof a$5){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=Li(r);}catch(i){console.error(`Error parsing Zod error in ${t}:`,i),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 Li(e){let t=e.flatten(),r=Object.entries(t.fieldErrors).map(([n,s])=>`${n}: ${(s??[]).join(", ")}`),o=t.formErrors;return [...r,...o].filter(Boolean).join("; ")}function _i(){let{frameAncestors:e}=Or(),t=e&&e.length>0,r=t?["'self'",...e].join(" "):"'self'";return (o,i,n)=>{i.setHeader("Content-Security-Policy",`frame-ancestors ${r}`),t||i.setHeader("X-Frame-Options","SAMEORIGIN"),n();}}function Pi(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{R as a,yr as b,br as c,Er as d,vr as e,Pr as f,se as g,Vo as h,oi as i,ii as j,Xe as k,ni as l};//# sourceMappingURL=chunk-TJ626QWY.js.map
|
|
19
|
-
//# sourceMappingURL=chunk-TJ626QWY.js.map
|