@live-state/sync 0.0.4-beta.3 → 0.0.4-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { g as Client, f as ClientEvents, C as ClientOptions, e as ConnectionStateChangeEvent, M as MessageReceivedEvent, d as SubscriptionProvider, h as createClient, u as useLiveQuery } from './index-
|
|
1
|
+
export { g as Client, f as ClientEvents, C as ClientOptions, e as ConnectionStateChangeEvent, M as MessageReceivedEvent, d as SubscriptionProvider, h as createClient, u as useLiveQuery } from './index-BjkfU9Th.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'zod';
|
|
4
4
|
import 'zod/v3';
|
package/dist/fetch-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AnyRouter, C as ClientOptions, L as LiveObjectAny, W as WhereClause, I as IncludeClause, S as Simplify, a as InferLiveObject, b as InferInsert, c as InferUpdate } from './index-
|
|
1
|
+
import { A as AnyRouter, C as ClientOptions, L as LiveObjectAny, W as WhereClause, I as IncludeClause, S as Simplify, a as InferLiveObject, b as InferInsert, c as InferUpdate } from './index-BjkfU9Th.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'zod';
|
|
4
4
|
import 'zod/v3';
|
|
@@ -234,7 +234,7 @@ declare class Router<TRoutes extends RouteRecord> {
|
|
|
234
234
|
routes: TRoutes;
|
|
235
235
|
}): Router<TRoutes>;
|
|
236
236
|
}
|
|
237
|
-
type AnyRouter = Router<
|
|
237
|
+
type AnyRouter = Router<any>;
|
|
238
238
|
type RequestHandler<TInput, TResult, TSchema extends Schema<any> = Schema<any>> = (opts: {
|
|
239
239
|
req: ParsedRequest<TInput>;
|
|
240
240
|
db: Storage;
|
|
@@ -282,7 +282,7 @@ declare class Route<TResourceSchema extends LiveObjectAny, TMiddleware extends M
|
|
|
282
282
|
private handleFind;
|
|
283
283
|
private handleSet;
|
|
284
284
|
}
|
|
285
|
-
type AnyRoute = Route<
|
|
285
|
+
type AnyRoute = Route<LiveObjectAny, Middleware<any>, Record<string, any>>;
|
|
286
286
|
|
|
287
287
|
/** biome-ignore-all lint/suspicious/noExplicitAny: false positive */
|
|
288
288
|
|
package/dist/server.d.cts
CHANGED
|
@@ -40,11 +40,11 @@ declare class Router<TRoutes extends RouteRecord> {
|
|
|
40
40
|
routes: TRoutes;
|
|
41
41
|
}): Router<TRoutes>;
|
|
42
42
|
}
|
|
43
|
-
declare const router: <TSchema extends Schema<any>, TRoutes extends Record<keyof TSchema,
|
|
43
|
+
declare const router: <TSchema extends Schema<any>, TRoutes extends Record<keyof TSchema, Route<any, any, any>>>(opts: {
|
|
44
44
|
schema: TSchema;
|
|
45
45
|
routes: TRoutes;
|
|
46
46
|
}) => Router<TRoutes>;
|
|
47
|
-
type AnyRouter = Router<
|
|
47
|
+
type AnyRouter = Router<any>;
|
|
48
48
|
type QueryResult<TShape extends LiveObjectAny> = {
|
|
49
49
|
data: Record<string, MaterializedLiveType<TShape>>;
|
|
50
50
|
};
|
|
@@ -107,7 +107,7 @@ declare class RouteFactory {
|
|
|
107
107
|
static create(): RouteFactory;
|
|
108
108
|
}
|
|
109
109
|
declare const routeFactory: typeof RouteFactory.create;
|
|
110
|
-
type AnyRoute = Route<
|
|
110
|
+
type AnyRoute = Route<LiveObjectAny, Middleware<any>, Record<string, any>>;
|
|
111
111
|
|
|
112
112
|
/** biome-ignore-all lint/suspicious/noExplicitAny: false positive */
|
|
113
113
|
|
package/dist/server.d.ts
CHANGED
|
@@ -40,11 +40,11 @@ declare class Router<TRoutes extends RouteRecord> {
|
|
|
40
40
|
routes: TRoutes;
|
|
41
41
|
}): Router<TRoutes>;
|
|
42
42
|
}
|
|
43
|
-
declare const router: <TSchema extends Schema<any>, TRoutes extends Record<keyof TSchema,
|
|
43
|
+
declare const router: <TSchema extends Schema<any>, TRoutes extends Record<keyof TSchema, Route<any, any, any>>>(opts: {
|
|
44
44
|
schema: TSchema;
|
|
45
45
|
routes: TRoutes;
|
|
46
46
|
}) => Router<TRoutes>;
|
|
47
|
-
type AnyRouter = Router<
|
|
47
|
+
type AnyRouter = Router<any>;
|
|
48
48
|
type QueryResult<TShape extends LiveObjectAny> = {
|
|
49
49
|
data: Record<string, MaterializedLiveType<TShape>>;
|
|
50
50
|
};
|
|
@@ -107,7 +107,7 @@ declare class RouteFactory {
|
|
|
107
107
|
static create(): RouteFactory;
|
|
108
108
|
}
|
|
109
109
|
declare const routeFactory: typeof RouteFactory.create;
|
|
110
|
-
type AnyRoute = Route<
|
|
110
|
+
type AnyRoute = Route<LiveObjectAny, Middleware<any>, Record<string, any>>;
|
|
111
111
|
|
|
112
112
|
/** biome-ignore-all lint/suspicious/noExplicitAny: false positive */
|
|
113
113
|
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {a,b as b$1,r}from'./chunk-GNY3ZGE5.js';import Se,{parse}from'qs';import {z as z$1}from'zod';import j from'node:crypto';import'js-xxhash';import {Kysely,PostgresDialect}from'kysely';import {jsonObjectFrom,jsonArrayFrom}from'kysely/helpers/postgres';var C=a(O=>{Object.defineProperty(O,"__esModule",{value:true});O.parse=Te;O.serialize=ge;var le=/^[\u0021-\u003A\u003C\u003E-\u007E]+$/,pe=/^[\u0021-\u003A\u003C-\u007E]*$/,me=/^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,fe=/^[\u0020-\u003A\u003D-\u007E]*$/,ye=Object.prototype.toString,he=(()=>{let i=function(){};return i.prototype=Object.create(null),i})();function Te(i,e){let t=new he,r=i.length;if(r<2)return t;let n=(e==null?void 0:e.decode)||xe,a=0;do{let s=i.indexOf("=",a);if(s===-1)break;let c=i.indexOf(";",a),o=c===-1?r:c;if(s>o){a=i.lastIndexOf(";",s-1)+1;continue}let y=H(i,a,s),f=Z(i,s,y),u=i.slice(y,f);if(t[u]===void 0){let d=H(i,s+1,o),p=Z(i,o,d),l=n(i.slice(d,p));t[u]=l;}a=o+1;}while(a<r);return t}function H(i,e,t){do{let r=i.charCodeAt(e);if(r!==32&&r!==9)return e}while(++e<t);return t}function Z(i,e,t){for(;e>t;){let r=i.charCodeAt(--e);if(r!==32&&r!==9)return e+1}return t}function ge(i,e,t){let r=(t==null?void 0:t.encode)||encodeURIComponent;if(!le.test(i))throw new TypeError(`argument name is invalid: ${i}`);let n=r(e);if(!pe.test(n))throw new TypeError(`argument val is invalid: ${e}`);let a=i+"="+n;if(!t)return a;if(t.maxAge!==void 0){if(!Number.isInteger(t.maxAge))throw new TypeError(`option maxAge is invalid: ${t.maxAge}`);a+="; Max-Age="+t.maxAge;}if(t.domain){if(!me.test(t.domain))throw new TypeError(`option domain is invalid: ${t.domain}`);a+="; Domain="+t.domain;}if(t.path){if(!fe.test(t.path))throw new TypeError(`option path is invalid: ${t.path}`);a+="; Path="+t.path;}if(t.expires){if(!Re(t.expires)||!Number.isFinite(t.expires.valueOf()))throw new TypeError(`option expires is invalid: ${t.expires}`);a+="; Expires="+t.expires.toUTCString();}if(t.httpOnly&&(a+="; HttpOnly"),t.secure&&(a+="; Secure"),t.partitioned&&(a+="; Partitioned"),t.priority)switch(typeof t.priority=="string"?t.priority.toLowerCase():void 0){case "low":a+="; Priority=Low";break;case "medium":a+="; Priority=Medium";break;case "high":a+="; Priority=High";break;default:throw new TypeError(`option priority is invalid: ${t.priority}`)}if(t.sameSite)switch(typeof t.sameSite=="string"?t.sameSite.toLowerCase():t.sameSite){case true:case "strict":a+="; SameSite=Strict";break;case "lax":a+="; SameSite=Lax";break;case "none":a+="; SameSite=None";break;default:throw new TypeError(`option sameSite is invalid: ${t.sameSite}`)}return a}function xe(i){if(i.indexOf("%")===-1)return i;try{return decodeURIComponent(i)}catch{return i}}function Re(i){return ye.call(i)==="[object Date]"}});var Q=b$1(C(),1);var L=z$1.object({resource:z$1.string(),where:z$1.record(z$1.string(),z$1.any()).optional(),include:z$1.record(z$1.string(),z$1.any()).optional(),lastSyncedAt:z$1.string().optional(),limit:z$1.number().optional(),sort:z$1.array(z$1.object({key:z$1.string(),direction:z$1.enum(["asc","desc"])})).optional()}),z=z$1.record(z$1.string(),z$1.object({value:z$1.string().or(z$1.number()).or(z$1.boolean()).or(z$1.date()).nullable(),_meta:z$1.object({timestamp:z$1.string().optional().nullable()}).optional()})).superRefine((i,e)=>{i.id&&e.addIssue({code:z$1.ZodIssueCode.custom,message:"Payload cannot have an id"});}),B=z$1.object({id:z$1.string().optional(),type:z$1.literal("MUTATE"),resource:z$1.string(),resourceId:z$1.string().optional()}),M=B.extend({procedure:z$1.string(),payload:z$1.any().optional()}),E=B.extend({procedure:z$1.enum(["INSERT","UPDATE"]),payload:z});z$1.union([E,M]);var G=L.omit({resource:true}),v=M.omit({id:true,type:true,resource:true,procedure:true}),N=E.omit({id:true,type:true,resource:true,procedure:true});z$1.union([N,v]);var K=i=>async e=>{var t;try{let r=typeof e.headers.getSetCookie=="function"?Object.fromEntries(e.headers):e.headers,n={headers:r,cookies:r.cookie?Q.default.parse(r.cookie):{}},a=new URL(e.url),s=a.pathname.split("/"),c=a.searchParams,o=Se.parse(c.toString()),y=await((t=i.contextProvider)==null?void 0:t.call(i,{transport:"HTTP",headers:n.headers,cookies:n.cookies,query:o}))??{};if(e.method==="GET"){let f=s[s.length-1],{success:u,data:d,error:p}=G.safeParse(o);if(!u)return Response.json({message:"Invalid query",code:"INVALID_QUERY",details:p},{status:400});let l=await i.handleRequest({req:{...n,type:"QUERY",resourceName:f,context:y,where:d.where,include:d.include,query:o}});return !l||!l.data?Response.json({message:"Invalid resource",code:"INVALID_RESOURCE"},{status:400}):Response.json(l.data)}if(e.method==="POST")try{let f=s[s.length-1],u=s[s.length-2],d=e.body?await e.json():{},p;if(f==="insert"||f==="update"){let{success:T,data:g,error:R}=N.safeParse(d);if(!T)return Response.json({message:"Invalid mutation",code:"INVALID_REQUEST",details:R},{status:400});p=g;}else {let{success:T,data:g,error:R}=v.safeParse(d);if(!T)return Response.json({message:"Invalid mutation",code:"INVALID_REQUEST",details:R},{status:400});p=g;}let l=await i.handleRequest({req:{...n,type:"MUTATE",resourceName:u,input:p.payload,context:y,resourceId:p.resourceId,procedure:f==="insert"||f==="update"?f.toUpperCase():f,query:{}}});return Response.json(l)}catch(f){return console.error("Error parsing mutation from the client:",f),Response.json({message:"Internal server error",code:"INTERNAL_SERVER_ERROR"},{status:500})}return Response.json({message:"Not found",code:"NOT_FOUND"},{status:404})}catch(r){return console.error("Unexpected error:",r),Response.json({message:"Internal server error",code:"INTERNAL_SERVER_ERROR"},{status:500})}};var ne=b$1(C(),1);var I=z$1.string(),we=z$1.object({id:I,type:z$1.literal("SUBSCRIBE"),resource:z$1.string()}),Ie=L.extend({id:I,type:z$1.literal("QUERY")}),J=E.extend({id:I}),Me=M.extend({id:I}),Ee=z$1.union([Me,J]),Y=z$1.union([we,Ie,Ee]),Ae=z$1.object({id:I,type:z$1.literal("REJECT"),resource:z$1.string(),message:z$1.string().optional()}),$e=z$1.object({id:I,type:z$1.literal("REPLY"),data:z$1.any()});z$1.union([Ae,$e,J]);z$1.object({resource:z$1.string(),data:z$1.record(z$1.string(),z)});var ee="0123456789ABCDEFGHJKMNPQRSTVWXYZ",A=32;var Oe=16,te=10,X=0xffffffffffff;var S;(function(i){i.Base32IncorrectEncoding="B32_ENC_INVALID",i.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",i.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",i.EncodeTimeNegative="ENC_TIME_NEG",i.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",i.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",i.PRNGDetectFailure="PRNG_DETECT",i.ULIDInvalid="ULID_INVALID",i.Unexpected="UNEXPECTED",i.UUIDInvalid="UUID_INVALID";})(S||(S={}));var w=class extends Error{constructor(e,t){super(`${t} (${e})`),this.name="ULIDError",this.code=e;}};function Le(i){let e=Math.floor(i()*A);return e===A&&(e=A-1),ee.charAt(e)}function je(i){var r;let e=Pe(),t=e&&(e.crypto||e.msCrypto)||(typeof j<"u"?j:null);if(typeof(t==null?void 0:t.getRandomValues)=="function")return ()=>{let n=new Uint8Array(1);return t.getRandomValues(n),n[0]/255};if(typeof(t==null?void 0:t.randomBytes)=="function")return ()=>t.randomBytes(1).readUInt8()/255;if((r=j)!=null&&r.randomBytes)return ()=>j.randomBytes(1).readUInt8()/255;throw new w(S.PRNGDetectFailure,"Failed to find a reliable PRNG")}function Pe(){return ve()?self:typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:null}function Ce(i,e){let t="";for(;i>0;i--)t=Le(e)+t;return t}function ze(i,e=te){if(isNaN(i))throw new w(S.EncodeTimeValueMalformed,`Time must be a number: ${i}`);if(i>X)throw new w(S.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${X}: ${i}`);if(i<0)throw new w(S.EncodeTimeNegative,`Time must be positive: ${i}`);if(Number.isInteger(i)===false)throw new w(S.EncodeTimeValueMalformed,`Time must be an integer: ${i}`);let t,r="";for(let n=e;n>0;n--)t=i%A,r=ee.charAt(t)+r,i=(i-t)/A;return r}function ve(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function re(i,e){let t=je(),r=Date.now();return ze(r,te)+Ce(Oe,t)}var U=()=>re().toLowerCase();var ie=i=>{let e={},t={};return i.subscribeToMutations(r=>{let n=r;!n.resourceId||!n.payload||(console.log("Mutation propagated:",n),Object.entries(t[n.resource]??{}).forEach(([a,s])=>{var c;(c=e[a])==null||c.send(JSON.stringify({...n,id:n.id??U()}));}));}),(r,n)=>{var f;let a=u=>{r.send(JSON.stringify(u));},s=U(),c={headers:n.headers,cookies:typeof n.headers.cookie=="string"?ne.default.parse(n.headers.cookie):{}},o=parse(n.url.split("?")[1]),y=(f=i.contextProvider)==null?void 0:f.call(i,{transport:"WEBSOCKET",headers:c.headers,cookies:c.cookies,query:o});e[s]=r,console.log("Client connected:",s),r.on("message",async u=>{try{console.log("Message received from the client:",u);let d=Y.parse(JSON.parse(u.toString()));if(d.type==="SUBSCRIBE"){let{resource:p}=d;t[p]||(t[p]={}),t[p][s]={};}else if(d.type==="QUERY"){let{resource:p}=d,l=await i.handleRequest({req:{...c,type:"QUERY",resourceName:p,context:await y??{},query:o}});if(!l||!l.data)throw new Error("Invalid resource");a({id:d.id,type:"REPLY",data:{resource:p,data:Object.fromEntries(Object.entries(l.data??{}).map(([T,g])=>[T,g.value]))}});}else if(d.type==="MUTATE"){let{resource:p}=d;console.log("Received mutation from client:",d);try{let l=await i.handleRequest({req:{...c,type:"MUTATE",resourceName:p,input:d.payload,context:{messageId:d.id,...await y??{}},resourceId:d.resourceId,procedure:d.procedure,query:o}});d.procedure&&d.procedure!=="INSERT"&&d.procedure!=="UPDATE"&&a({id:d.id,type:"REPLY",data:l});}catch(l){a({id:d.id,type:"REJECT",resource:p,message:l.message}),console.error("Error parsing mutation from the client:",l);}}}catch(d){console.error("Error handling message from the client:",d);}}),r.on("close",()=>{console.log("Connection closed",s),delete e[s];for(let u of Object.values(t))delete u[s];});}};function oe(i){let e=`${i.protocol}://${i.hostname}${i.url}`,t=new Headers;return Object.entries(i.headers).forEach(([r,n])=>{n&&t.set(r,Array.isArray(n)?n.join(","):n);}),new Request(e,{method:i.method,headers:t,body:i.body&&i.method!=="GET"?JSON.stringify(i.body):void 0})}var Tt=(i,e,t)=>{i.ws(`${(t==null?void 0:t.basePath)??""}/ws`,ie(e)),i.use(`${(t==null?void 0:t.basePath)??""}/`,(r,n)=>{K(e)(oe(r)).then(s=>s.json().then(c=>n.status(s.status).send(c)));});};var b=(i,e,t=false)=>Object.entries(e).every(([r,n])=>{if(r==="$and")return n.every(s=>b(i,s,t));if(r==="$or")return n.some(s=>b(i,s,t));let a=(n==null?void 0:n.$eq)!==void 0?n==null?void 0:n.$eq:n;if(typeof n=="object"&&n!==null&&(n==null?void 0:n.$eq)===void 0){if(n.$in!==void 0){let s=i[r];return s===void 0?false:t?!n.$in.includes(s):n.$in.includes(s)}if(n.$not!==void 0&&!t)return b(i,{[r]:n.$not},true);if(n.$gt!==void 0){let s=i[r];return typeof s!="number"?false:t?s<=n.$gt:s>n.$gt}if(n.$gte!==void 0){let s=i[r];return typeof s!="number"?false:t?s<n.$gte:s>=n.$gte}if(n.$lt!==void 0){let s=i[r];return typeof s!="number"?false:t?s>=n.$lt:s<n.$lt}if(n.$lte!==void 0){let s=i[r];return typeof s!="number"?false:t?s>n.$lte:s<=n.$lte}return !i[r]||typeof i[r]!="object"?false:b(i[r],n,t)}return t?i[r]!==a:i[r]===a});var D=class i{routes;constructor(e){this.routes=e.routes;}static create(e){return new i(e)}},Mt=i=>D.create({...i}),De=i=>({handler:e=>({inputValidator:i??z$1.undefined(),handler:e})}),_=class i{_resourceSchema;resourceName;middlewares;customMutations;authorization;constructor(e,t,r){this.resourceName=e,this.middlewares=new Set,this.customMutations=t??{},this.authorization=r;}async handleRequest(e){let t=r=>(()=>{if(r.type==="QUERY")return this.handleFind({req:r,db:e.db,schema:e.schema});if(r.type==="MUTATE"){if(!r.procedure)throw new Error("Procedure is required for mutations");let n=this.customMutations[r.procedure];if(n){let a=n.inputValidator.parse(r.input);return r.input=a,n.handler({req:r,db:e.db,schema:e.schema})}else if(r.procedure==="INSERT"||r.procedure==="UPDATE")return this.handleSet({req:r,db:e.db,schema:e.schema,operation:r.procedure})}throw new Error("Invalid request")})();return await Array.from(this.middlewares.values()).reduceRight((r,n)=>a=>n({req:a,next:r}),async r=>t(r))(e.req)}use(...e){for(let t of e)this.middlewares.add(t);return this}withMutations(e){return new i(this.resourceName,e({mutation:De}))}handleFind=async({req:e,db:t})=>{var n,a;let r=(a=(n=this.authorization)==null?void 0:n.read)==null?void 0:a.call(n,{ctx:e.context});if(typeof r=="boolean"&&!r)throw new Error("Not authorized");return {data:await t.rawFind(e.resourceName,e.where&&r&&r!==true?{$and:[e.where,r]}:r&&r!==true?r:e.where,e.include),acceptedValues:null}};handleSet=async({req:e,db:t,schema:r$1,operation:n})=>{if(!e.input)throw new Error("Payload is required");if(!e.resourceId)throw new Error("ResourceId is required");let a=await t.rawFindById(e.resourceName,e.resourceId);if(n==="INSERT"&&a)throw new Error("Resource already exists");if(n==="UPDATE"&&!a)throw new Error("Resource not found");return t.transaction(async({trx:s})=>{var f,u,d,p,l;let[c,o]=r$1[this.resourceName].mergeMutation("set",e.input,a);if(!o)throw new Error("Mutation rejected");if(n==="INSERT"){let T=await s.rawInsert(e.resourceName,e.resourceId,c);if((f=this.authorization)!=null&&f.insert){let g=r(T);g.id=g.id??e.resourceId;let R=this.authorization.insert({ctx:e.context,value:g});if(!(typeof R=="boolean"?R:b(g,R)))throw new Error("Not authorized")}return {data:T,acceptedValues:o}}if((d=(u=this.authorization)==null?void 0:u.update)!=null&&d.preMutation){let T=r(a);T.id=T.id??e.resourceId;let g=this.authorization.update.preMutation({ctx:e.context,value:T});if(!(typeof g=="boolean"?g:b(T,g)))throw new Error("Not authorized")}let y=await s.rawUpdate(e.resourceName,e.resourceId,c);if((l=(p=this.authorization)==null?void 0:p.update)!=null&&l.postMutation){let T=r(y);T.id=T.id??e.resourceId;let g=this.authorization.update.postMutation({ctx:e.context,value:T});if(!(typeof g=="boolean"?g:b(T,g)))throw new Error("Not authorized")}return {data:y,acceptedValues:o}})}},V=class i{middlewares;constructor(e=[]){this.middlewares=e;}collectionRoute(e,t){return new _(e.name,void 0,t).use(...this.middlewares)}use(...e){return new i([...this.middlewares,...e])}static create(){return new i}},Et=V.create;var $=class{async insert(e,t){let r$1=new Date().toISOString();return r(await this.rawInsert(e.name,t.id,{value:Object.fromEntries(Object.entries(t).map(([n,a])=>[n,{value:a,_meta:{timestamp:r$1}}]))}))}async update(e,t,r$1){let n=new Date().toISOString(),{id:a,...s}=r$1;return r(await this.rawUpdate(e.name,t,{value:Object.fromEntries(Object.entries(s).map(([c,o])=>[c,{value:o,_meta:{timestamp:n}}]))}))}};function P(i,e,t,r){if(!i)throw new Error("Schema not initialized");let n=i[e];if(!n)throw new Error("Resource not found");let a=r.$or,s=r.$and;return (a?t.or:t.and)(a?r.$or.map(c=>P(i,e,t,c)):s?r.$and.map(c=>P(i,e,t,c)):Object.entries(r).map(([c,o])=>{var y,f;if(n.fields[c])return (o==null?void 0:o.$eq)!==void 0?t(`${e}.${c}`,o.$eq===null?"is":"=",o.$eq):(o==null?void 0:o.$in)!==void 0?t(`${e}.${c}`,"in",o.$in):(o==null?void 0:o.$not)!==void 0?((y=o==null?void 0:o.$not)==null?void 0:y.$in)!==void 0?t(`${e}.${c}`,"not in",o.$not.$in):((f=o==null?void 0:o.$not)==null?void 0:f.$eq)!==void 0?t(`${e}.${c}`,o.$not.$eq===null?"is not":"!=",o.$not.$eq):t(`${e}.${c}`,o.$not===null?"is not":"!=",o.$not):(o==null?void 0:o.$gt)!==void 0?t(`${e}.${c}`,">",o.$gt):(o==null?void 0:o.$gte)!==void 0?t(`${e}.${c}`,">=",o.$gte):(o==null?void 0:o.$lt)!==void 0?t(`${e}.${c}`,"<",o.$lt):(o==null?void 0:o.$lte)!==void 0?t(`${e}.${c}`,"<=",o.$lte):t(`${e}.${c}`,o===null?"is":"=",o);if(n.relations[c]){let u=n.relations[c],d=u.entity.name;u.type==="one"?"id":u.foreignColumn;u.type==="one"?u.relationalColumn:"id";return P(i,d,t,o)}return null}).filter(Boolean))}function Ve(i,e,t,r){let n=i[e];if(!n)throw new Error("Resource not found");if(!r)return t;for(let a of Object.keys(r)){if(!n.relations[a])continue;let s=n.relations[a],c=s.entity.name,o=s.type==="one"?"id":s.foreignColumn,y=s.type==="one"?s.relationalColumn:"id";t=t.leftJoin(c,`${c}.${o}`,`${e}.${y}`);}return t}function se(i,e,t,r){return !r||Object.keys(r).length===0?t:(t=Ve(i,e,t,r),t.where(n=>P(i,e,n,r)))}function k(i,e,t,r){if(!r)return t;if(!i)throw new Error("Schema not initialized");let n=i[e];if(!n)throw new Error(`Resource not found: ${e}`);for(let a of Object.keys(r)){if(!n.relations[a])throw new Error(`Relation ${a} not found in resource ${e}`);let s=n.relations[a],c=s.entity.name,o=s.type==="one"?"id":s.foreignColumn,y=s.type==="one"?s.relationalColumn:"id",f=s.type==="one"?jsonObjectFrom:jsonArrayFrom;t=t.select(u=>f(u.selectFrom(c).selectAll(c).whereRef(`${c}.${o}`,"=",`${e}.${y}`).select(d=>jsonObjectFrom(d.selectFrom(`${c}_meta`).selectAll(`${c}_meta`).whereRef(`${c}_meta.id`,"=",`${c}.id`)).as("_meta"))).as(a));}return t}var F=class i extends ${db;schema;constructor(e,t){super(),this.isKyselyLike(e)?this.db=e:this.db=new Kysely({dialect:new PostgresDialect({pool:e})}),this.schema=t,this.rawInsert=this.rawInsert.bind(this),this.rawUpdate=this.rawUpdate.bind(this);}async updateSchema(e){this.schema=e;let t=await this.db.introspection.getTables();for(let[r,n]of Object.entries(e)){let a=t.find(o=>o.name===r);a||await this.db.schema.createTable(r).ifNotExists().execute();let s=`${r}_meta`,c=t.find(o=>o.name===s);c||await this.db.schema.createTable(s).ifNotExists().execute();for(let[o,y]of Object.entries(n.fields)){let f=a==null?void 0:a.columns.find(p=>p.name===o),u=y.getStorageFieldType();f?f.dataType!==u.type&&console.error("Column type mismatch:",o,"expected to have type:",u.type,"but has type:",f.dataType):(await this.db.schema.alterTable(r).addColumn(o,u.type,p=>{let l=p;return u.unique&&(l=l.unique()),u.nullable||(l=l.notNull()),u.references&&(l=l.references(u.references)),u.primary&&(l=l.primaryKey()),u.default!==void 0&&(l=l.defaultTo(u.default)),l}).execute().catch(p=>{throw console.error("Error adding column",o,p),p}),u.index&&await this.db.schema.createIndex(`${r}_${o}_index`).on(r).column(o).execute().catch(p=>{})),(c==null?void 0:c.columns.find(p=>p.name===o))||await this.db.schema.alterTable(s).addColumn(o,"varchar",p=>{let l=p;return u.primary&&(l=l.primaryKey().references(`${r}.${o}`)),l}).execute();}}}async rawFindById(e,t,r){if(!this.schema)throw new Error("Schema not initialized");let n=await this.db.selectFrom(e).where("id","=",t).selectAll(e).select(s=>jsonObjectFrom(s.selectFrom(`${e}_meta`).selectAll(`${e}_meta`).whereRef(`${e}_meta.id`,"=",`${e}.id`)).as("_meta"));n=k(this.schema,e,n,r);let a=await n.executeTakeFirst();if(a)return this.convertToMaterializedLiveType(a)}async findOne(e,t,r$1){let n=await this.rawFindById(e.name,t,r$1==null?void 0:r$1.include);if(n)return r(n)}async rawFind(e,t,r){if(!this.schema)throw new Error("Schema not initialized");let n=this.db.selectFrom(e).selectAll(e).select(o=>jsonObjectFrom(o.selectFrom(`${e}_meta`).selectAll(`${e}_meta`).whereRef(`${e}_meta.id`,"=",`${e}.id`)).as("_meta"));n=se(this.schema,e,n,t),n=k(this.schema,e,n,r);let a=await n.execute(),s=Object.fromEntries(a.map(o=>{let{id:y,...f}=o;return [y,f]}));return Object.keys(s).length===0?{}:Object.entries(s).reduce((o,[y,f])=>(o[y]=this.convertToMaterializedLiveType(f),o),{})}async find(e,t){let r$1=await this.rawFind(e.name,t==null?void 0:t.where,t==null?void 0:t.include);return Object.fromEntries(Object.entries(r$1).map(([n,a])=>[n,r(a)]))}async rawInsert(e,t,r){var s;let n={},a={};for(let[c,o]of Object.entries(r.value)){let y=(s=o._meta)==null?void 0:s.timestamp;y&&(n[c]=o.value,a[c]=y);}return await this.db.insertInto(e).values({...n,id:t}).execute().then(()=>{this.db.insertInto(`${e}_meta`).values({...a,id:t}).execute();}),r}async rawUpdate(e,t,r){var s;let n={},a={};for(let[c,o]of Object.entries(r.value)){let y=(s=o._meta)==null?void 0:s.timestamp;y&&(n[c]=o.value,a[c]=y);}return await Promise.all([this.db.updateTable(e).set(n).where("id","=",t).execute(),this.db.insertInto(`${e}_meta`).values({...a,id:t}).onConflict(c=>c.column("id").doUpdateSet(a)).execute()]),r}async transaction(e){if(!this.schema)throw new Error("Schema not initialized");if(this.db.isTransaction){let r=Math.random().toString(36).substring(2,15),n=await this.db.savepoint(r).execute();try{return await e({trx:this,commit:()=>n.releaseSavepoint(r).execute().then(()=>{}),rollback:()=>n.rollbackToSavepoint(r).execute().then(()=>{})}).then(a=>n.isCommitted||n.isRolledBack?a:n.releaseSavepoint(r).execute().then(()=>a))}catch(a){throw await n.rollbackToSavepoint(r).execute().catch(()=>{}),a}}let t=await this.db.startTransaction().execute();try{return await e({trx:new i(t,this.schema),commit:()=>t.commit().execute(),rollback:()=>t.rollback().execute()}).then(r=>t.isCommitted||t.isRolledBack?r:t.commit().execute().then(()=>r))}catch(r){throw await t.rollback().execute(),r}}convertToMaterializedLiveType(e){return {value:Object.entries(e).reduce((t,[r,n])=>{var a,s,c;return r==="_meta"||(r==="id"?t[r]={value:n}:Array.isArray(n)?t[r]={value:n.map(o=>this.convertToMaterializedLiveType(o)),_meta:{timestamp:(a=e==null?void 0:e._meta)==null?void 0:a[r]}}:typeof n=="object"&&n!==null&&!(n instanceof Date)?t[r]={...this.convertToMaterializedLiveType(n),_meta:{timestamp:(s=e==null?void 0:e._meta)==null?void 0:s[r]}}:t[r]={value:n,_meta:{timestamp:(c=e==null?void 0:e._meta)==null?void 0:c[r]}}),t},{})}}isKyselyLike(e){if(e instanceof Kysely)return true;if(!e||typeof e!="object")return false;let t=e,r=typeof t.selectFrom=="function",n=typeof t.startTransaction=="function",a=typeof t.savepoint=="function",s=typeof t.isTransaction=="boolean"||typeof t.isTransaction=="function";return r&&n||a&&s}};var q=class i{router;storage;schema;middlewares=new Set;contextProvider;mutationSubscriptions=new Set;constructor(e){var t;this.router=e.router,this.storage=e.storage,this.schema=e.schema,(t=e.middlewares)==null||t.forEach(r=>{this.middlewares.add(r);}),this.storage.updateSchema(this.schema),this.contextProvider=e.contextProvider;}static create(e){return new i(e)}subscribeToMutations(e){return this.mutationSubscriptions.add(e),()=>{this.mutationSubscriptions.delete(e);}}async handleRequest(e){if(!this.router.routes[e.req.resourceName])throw new Error("Invalid resource");let t=await Array.from(this.middlewares.values()).reduceRight((r,n)=>a=>n({req:a,next:r}),async r=>this.router.routes[e.req.resourceName].handleRequest({req:r,db:this.storage,schema:this.schema}))(e.req);return t&&e.req.type==="MUTATE"&&t.acceptedValues&&Object.keys(t.acceptedValues).length>0&&(e.req.procedure==="INSERT"||e.req.procedure==="UPDATE")&&this.mutationSubscriptions.forEach(r=>{r({id:e.req.context.messageId,type:"MUTATE",resource:e.req.resourceName,payload:t.acceptedValues??{},resourceId:e.req.resourceId,procedure:e.req.procedure});}),t}use(e){return this.middlewares.add(e),this}context(e){return this.contextProvider=e,this}},kt=q.create;
|
|
1
|
+
import {a,b,r}from'./chunk-GNY3ZGE5.js';import Se,{parse}from'qs';import {z as z$1}from'zod';import j from'node:crypto';import'js-xxhash';import {Kysely,PostgresDialect}from'kysely';import {jsonObjectFrom,jsonArrayFrom}from'kysely/helpers/postgres';var C=a(O=>{Object.defineProperty(O,"__esModule",{value:true});O.parse=Te;O.serialize=ge;var le=/^[\u0021-\u003A\u003C\u003E-\u007E]+$/,pe=/^[\u0021-\u003A\u003C-\u007E]*$/,me=/^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,fe=/^[\u0020-\u003A\u003D-\u007E]*$/,ye=Object.prototype.toString,he=(()=>{let i=function(){};return i.prototype=Object.create(null),i})();function Te(i,e){let t=new he,r=i.length;if(r<2)return t;let n=(e==null?void 0:e.decode)||xe,a=0;do{let s=i.indexOf("=",a);if(s===-1)break;let c=i.indexOf(";",a),o=c===-1?r:c;if(s>o){a=i.lastIndexOf(";",s-1)+1;continue}let y=H(i,a,s),f=Z(i,s,y),u=i.slice(y,f);if(t[u]===void 0){let d=H(i,s+1,o),p=Z(i,o,d),l=n(i.slice(d,p));t[u]=l;}a=o+1;}while(a<r);return t}function H(i,e,t){do{let r=i.charCodeAt(e);if(r!==32&&r!==9)return e}while(++e<t);return t}function Z(i,e,t){for(;e>t;){let r=i.charCodeAt(--e);if(r!==32&&r!==9)return e+1}return t}function ge(i,e,t){let r=(t==null?void 0:t.encode)||encodeURIComponent;if(!le.test(i))throw new TypeError(`argument name is invalid: ${i}`);let n=r(e);if(!pe.test(n))throw new TypeError(`argument val is invalid: ${e}`);let a=i+"="+n;if(!t)return a;if(t.maxAge!==void 0){if(!Number.isInteger(t.maxAge))throw new TypeError(`option maxAge is invalid: ${t.maxAge}`);a+="; Max-Age="+t.maxAge;}if(t.domain){if(!me.test(t.domain))throw new TypeError(`option domain is invalid: ${t.domain}`);a+="; Domain="+t.domain;}if(t.path){if(!fe.test(t.path))throw new TypeError(`option path is invalid: ${t.path}`);a+="; Path="+t.path;}if(t.expires){if(!be(t.expires)||!Number.isFinite(t.expires.valueOf()))throw new TypeError(`option expires is invalid: ${t.expires}`);a+="; Expires="+t.expires.toUTCString();}if(t.httpOnly&&(a+="; HttpOnly"),t.secure&&(a+="; Secure"),t.partitioned&&(a+="; Partitioned"),t.priority)switch(typeof t.priority=="string"?t.priority.toLowerCase():void 0){case "low":a+="; Priority=Low";break;case "medium":a+="; Priority=Medium";break;case "high":a+="; Priority=High";break;default:throw new TypeError(`option priority is invalid: ${t.priority}`)}if(t.sameSite)switch(typeof t.sameSite=="string"?t.sameSite.toLowerCase():t.sameSite){case true:case "strict":a+="; SameSite=Strict";break;case "lax":a+="; SameSite=Lax";break;case "none":a+="; SameSite=None";break;default:throw new TypeError(`option sameSite is invalid: ${t.sameSite}`)}return a}function xe(i){if(i.indexOf("%")===-1)return i;try{return decodeURIComponent(i)}catch{return i}}function be(i){return ye.call(i)==="[object Date]"}});var Q=b(C(),1);var L=z$1.object({resource:z$1.string(),where:z$1.record(z$1.string(),z$1.any()).optional(),include:z$1.record(z$1.string(),z$1.any()).optional(),lastSyncedAt:z$1.string().optional(),limit:z$1.number().optional(),sort:z$1.array(z$1.object({key:z$1.string(),direction:z$1.enum(["asc","desc"])})).optional()}),z=z$1.record(z$1.string(),z$1.object({value:z$1.string().or(z$1.number()).or(z$1.boolean()).or(z$1.date()).nullable(),_meta:z$1.object({timestamp:z$1.string().optional().nullable()}).optional()})).superRefine((i,e)=>{i.id&&e.addIssue({code:z$1.ZodIssueCode.custom,message:"Payload cannot have an id"});}),B=z$1.object({id:z$1.string().optional(),type:z$1.literal("MUTATE"),resource:z$1.string(),resourceId:z$1.string().optional()}),M=B.extend({procedure:z$1.string(),payload:z$1.any().optional()}),E=B.extend({procedure:z$1.enum(["INSERT","UPDATE"]),payload:z});z$1.union([E,M]);var G=L.omit({resource:true}),v=M.omit({id:true,type:true,resource:true,procedure:true}),N=E.omit({id:true,type:true,resource:true,procedure:true});z$1.union([N,v]);var K=i=>async e=>{var t;try{let r=typeof e.headers.getSetCookie=="function"?Object.fromEntries(e.headers):e.headers,n={headers:r,cookies:r.cookie?Q.default.parse(r.cookie):{}},a=new URL(e.url),s=a.pathname.split("/"),c=a.searchParams,o=Se.parse(c.toString()),y=await((t=i.contextProvider)==null?void 0:t.call(i,{transport:"HTTP",headers:n.headers,cookies:n.cookies,query:o}))??{};if(e.method==="GET"){let f=s[s.length-1],{success:u,data:d,error:p}=G.safeParse(o);if(!u)return Response.json({message:"Invalid query",code:"INVALID_QUERY",details:p},{status:400});let l=await i.handleRequest({req:{...n,type:"QUERY",resourceName:f,context:y,where:d.where,include:d.include,query:o}});return !l||!l.data?Response.json({message:"Invalid resource",code:"INVALID_RESOURCE"},{status:400}):Response.json(l.data)}if(e.method==="POST")try{let f=s[s.length-1],u=s[s.length-2],d=e.body?await e.json():{},p;if(f==="insert"||f==="update"){let{success:T,data:g,error:b}=N.safeParse(d);if(!T)return Response.json({message:"Invalid mutation",code:"INVALID_REQUEST",details:b},{status:400});p=g;}else {let{success:T,data:g,error:b}=v.safeParse(d);if(!T)return Response.json({message:"Invalid mutation",code:"INVALID_REQUEST",details:b},{status:400});p=g;}let l=await i.handleRequest({req:{...n,type:"MUTATE",resourceName:u,input:p.payload,context:y,resourceId:p.resourceId,procedure:f==="insert"||f==="update"?f.toUpperCase():f,query:{}}});return Response.json(l)}catch(f){return console.error("Error parsing mutation from the client:",f),Response.json({message:"Internal server error",code:"INTERNAL_SERVER_ERROR"},{status:500})}return Response.json({message:"Not found",code:"NOT_FOUND"},{status:404})}catch(r){return console.error("Unexpected error:",r),Response.json({message:"Internal server error",code:"INTERNAL_SERVER_ERROR"},{status:500})}};var ne=b(C(),1);var I=z$1.string(),we=z$1.object({id:I,type:z$1.literal("SUBSCRIBE"),resource:z$1.string()}),Ie=L.extend({id:I,type:z$1.literal("QUERY")}),J=E.extend({id:I}),Me=M.extend({id:I}),Ee=z$1.union([Me,J]),Y=z$1.union([we,Ie,Ee]),Ae=z$1.object({id:I,type:z$1.literal("REJECT"),resource:z$1.string(),message:z$1.string().optional()}),$e=z$1.object({id:I,type:z$1.literal("REPLY"),data:z$1.any()});z$1.union([Ae,$e,J]);z$1.object({resource:z$1.string(),data:z$1.record(z$1.string(),z)});var ee="0123456789ABCDEFGHJKMNPQRSTVWXYZ",A=32;var Oe=16,te=10,X=0xffffffffffff;var S;(function(i){i.Base32IncorrectEncoding="B32_ENC_INVALID",i.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",i.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",i.EncodeTimeNegative="ENC_TIME_NEG",i.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",i.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",i.PRNGDetectFailure="PRNG_DETECT",i.ULIDInvalid="ULID_INVALID",i.Unexpected="UNEXPECTED",i.UUIDInvalid="UUID_INVALID";})(S||(S={}));var w=class extends Error{constructor(e,t){super(`${t} (${e})`),this.name="ULIDError",this.code=e;}};function Le(i){let e=Math.floor(i()*A);return e===A&&(e=A-1),ee.charAt(e)}function je(i){var r;let e=Pe(),t=e&&(e.crypto||e.msCrypto)||(typeof j<"u"?j:null);if(typeof(t==null?void 0:t.getRandomValues)=="function")return ()=>{let n=new Uint8Array(1);return t.getRandomValues(n),n[0]/255};if(typeof(t==null?void 0:t.randomBytes)=="function")return ()=>t.randomBytes(1).readUInt8()/255;if((r=j)!=null&&r.randomBytes)return ()=>j.randomBytes(1).readUInt8()/255;throw new w(S.PRNGDetectFailure,"Failed to find a reliable PRNG")}function Pe(){return ve()?self:typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:null}function Ce(i,e){let t="";for(;i>0;i--)t=Le(e)+t;return t}function ze(i,e=te){if(isNaN(i))throw new w(S.EncodeTimeValueMalformed,`Time must be a number: ${i}`);if(i>X)throw new w(S.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${X}: ${i}`);if(i<0)throw new w(S.EncodeTimeNegative,`Time must be positive: ${i}`);if(Number.isInteger(i)===false)throw new w(S.EncodeTimeValueMalformed,`Time must be an integer: ${i}`);let t,r="";for(let n=e;n>0;n--)t=i%A,r=ee.charAt(t)+r,i=(i-t)/A;return r}function ve(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function re(i,e){let t=je(),r=Date.now();return ze(r,te)+Ce(Oe,t)}var U=()=>re().toLowerCase();var ie=i=>{let e={},t={};return i.subscribeToMutations(r=>{let n=r;!n.resourceId||!n.payload||(console.log("Mutation propagated:",n),Object.entries(t[n.resource]??{}).forEach(([a,s])=>{var c;(c=e[a])==null||c.send(JSON.stringify({...n,id:n.id??U()}));}));}),(r,n)=>{var f;let a=u=>{r.send(JSON.stringify(u));},s=U(),c={headers:n.headers,cookies:typeof n.headers.cookie=="string"?ne.default.parse(n.headers.cookie):{}},o=parse(n.url.split("?")[1]),y=(f=i.contextProvider)==null?void 0:f.call(i,{transport:"WEBSOCKET",headers:c.headers,cookies:c.cookies,query:o});e[s]=r,console.log("Client connected:",s),r.on("message",async u=>{try{console.log("Message received from the client:",u);let d=Y.parse(JSON.parse(u.toString()));if(d.type==="SUBSCRIBE"){let{resource:p}=d;t[p]||(t[p]={}),t[p][s]={};}else if(d.type==="QUERY"){let{resource:p}=d,l=await i.handleRequest({req:{...c,type:"QUERY",resourceName:p,context:await y??{},query:o}});if(!l||!l.data)throw new Error("Invalid resource");a({id:d.id,type:"REPLY",data:{resource:p,data:Object.fromEntries(Object.entries(l.data??{}).map(([T,g])=>[T,g.value]))}});}else if(d.type==="MUTATE"){let{resource:p}=d;console.log("Received mutation from client:",d);try{let l=await i.handleRequest({req:{...c,type:"MUTATE",resourceName:p,input:d.payload,context:{messageId:d.id,...await y??{}},resourceId:d.resourceId,procedure:d.procedure,query:o}});d.procedure&&d.procedure!=="INSERT"&&d.procedure!=="UPDATE"&&a({id:d.id,type:"REPLY",data:l});}catch(l){a({id:d.id,type:"REJECT",resource:p,message:l.message}),console.error("Error parsing mutation from the client:",l);}}}catch(d){console.error("Error handling message from the client:",d);}}),r.on("close",()=>{console.log("Connection closed",s),delete e[s];for(let u of Object.values(t))delete u[s];});}};function oe(i){let e=`${i.protocol}://${i.hostname}${i.url}`,t=new Headers;return Object.entries(i.headers).forEach(([r,n])=>{n&&t.set(r,Array.isArray(n)?n.join(","):n);}),new Request(e,{method:i.method,headers:t,body:i.body&&i.method!=="GET"?JSON.stringify(i.body):void 0})}var Tt=(i,e,t)=>{i.ws(`${(t==null?void 0:t.basePath)??""}/ws`,ie(e)),i.use(`${(t==null?void 0:t.basePath)??""}/`,(r,n)=>{K(e)(oe(r)).then(s=>s.json().then(c=>n.status(s.status).send(c)));});};var R=(i,e,t=false)=>Object.entries(e).every(([r,n])=>{if(r==="$and")return n.every(s=>R(i,s,t));if(r==="$or")return n.some(s=>R(i,s,t));let a=(n==null?void 0:n.$eq)!==void 0?n==null?void 0:n.$eq:n;if(typeof n=="object"&&n!==null&&(n==null?void 0:n.$eq)===void 0){if(n.$in!==void 0){let s=i[r];return s===void 0?false:t?!n.$in.includes(s):n.$in.includes(s)}if(n.$not!==void 0&&!t)return R(i,{[r]:n.$not},true);if(n.$gt!==void 0){let s=i[r];return typeof s!="number"?false:t?s<=n.$gt:s>n.$gt}if(n.$gte!==void 0){let s=i[r];return typeof s!="number"?false:t?s<n.$gte:s>=n.$gte}if(n.$lt!==void 0){let s=i[r];return typeof s!="number"?false:t?s>=n.$lt:s<n.$lt}if(n.$lte!==void 0){let s=i[r];return typeof s!="number"?false:t?s>n.$lte:s<=n.$lte}return !i[r]||typeof i[r]!="object"?false:R(i[r],n,t)}return t?i[r]!==a:i[r]===a});var D=class i{routes;constructor(e){this.routes=e.routes;}static create(e){return new i(e)}},Mt=i=>D.create({...i}),De=i=>({handler:e=>({inputValidator:i??z$1.undefined(),handler:e})}),_=class i{_resourceSchema;resourceName;middlewares;customMutations;authorization;constructor(e,t,r){this.resourceName=e,this.middlewares=new Set,this.customMutations=t??{},this.authorization=r;}async handleRequest(e){let t=r=>(()=>{if(r.type==="QUERY")return this.handleFind({req:r,db:e.db,schema:e.schema});if(r.type==="MUTATE"){if(!r.procedure)throw new Error("Procedure is required for mutations");let n=this.customMutations[r.procedure];if(n){let a=n.inputValidator.parse(r.input);return r.input=a,n.handler({req:r,db:e.db,schema:e.schema})}else if(r.procedure==="INSERT"||r.procedure==="UPDATE")return this.handleSet({req:r,db:e.db,schema:e.schema,operation:r.procedure})}throw new Error("Invalid request")})();return await Array.from(this.middlewares.values()).reduceRight((r,n)=>a=>n({req:a,next:r}),async r=>t(r))(e.req)}use(...e){for(let t of e)this.middlewares.add(t);return this}withMutations(e){return new i(this.resourceName,e({mutation:De}))}handleFind=async({req:e,db:t})=>{var n,a;let r=(a=(n=this.authorization)==null?void 0:n.read)==null?void 0:a.call(n,{ctx:e.context});if(typeof r=="boolean"&&!r)throw new Error("Not authorized");return {data:await t.rawFind(e.resourceName,e.where&&r&&r!==true?{$and:[e.where,r]}:r&&r!==true?r:e.where,e.include),acceptedValues:null}};handleSet=async({req:e,db:t,schema:r$1,operation:n})=>{if(!e.input)throw new Error("Payload is required");if(!e.resourceId)throw new Error("ResourceId is required");let a=await t.rawFindById(e.resourceName,e.resourceId);if(n==="INSERT"&&a)throw new Error("Resource already exists");if(n==="UPDATE"&&!a)throw new Error("Resource not found");return t.transaction(async({trx:s})=>{var f,u,d,p,l;let[c,o]=r$1[this.resourceName].mergeMutation("set",e.input,a);if(!o)throw new Error("Mutation rejected");if(n==="INSERT"){let T=await s.rawInsert(e.resourceName,e.resourceId,c);if((f=this.authorization)!=null&&f.insert){let g=r(T);g.id=g.id??e.resourceId;let b=this.authorization.insert({ctx:e.context,value:g});if(!(typeof b=="boolean"?b:R(g,b)))throw new Error("Not authorized")}return {data:T,acceptedValues:o}}if((d=(u=this.authorization)==null?void 0:u.update)!=null&&d.preMutation){let T=r(a);T.id=T.id??e.resourceId;let g=this.authorization.update.preMutation({ctx:e.context,value:T});if(!(typeof g=="boolean"?g:R(T,g)))throw new Error("Not authorized")}let y=await s.rawUpdate(e.resourceName,e.resourceId,c);if((l=(p=this.authorization)==null?void 0:p.update)!=null&&l.postMutation){let T=r(y);T.id=T.id??e.resourceId;let g=this.authorization.update.postMutation({ctx:e.context,value:T});if(!(typeof g=="boolean"?g:R(T,g)))throw new Error("Not authorized")}return {data:y,acceptedValues:o}})}},V=class i{middlewares;constructor(e=[]){this.middlewares=e;}collectionRoute(e,t){return new _(e.name,void 0,t).use(...this.middlewares)}use(...e){return new i([...this.middlewares,...e])}static create(){return new i}},Et=V.create;var $=class{async insert(e,t){let r$1=new Date().toISOString();return r(await this.rawInsert(e.name,t.id,{value:Object.fromEntries(Object.entries(t).map(([n,a])=>[n,{value:a,_meta:{timestamp:r$1}}]))}))}async update(e,t,r$1){let n=new Date().toISOString(),{id:a,...s}=r$1;return r(await this.rawUpdate(e.name,t,{value:Object.fromEntries(Object.entries(s).map(([c,o])=>[c,{value:o,_meta:{timestamp:n}}]))}))}};function P(i,e,t,r){if(!i)throw new Error("Schema not initialized");let n=i[e];if(!n)throw new Error("Resource not found");let a=r.$or,s=r.$and;return (a?t.or:t.and)(a?r.$or.map(c=>P(i,e,t,c)):s?r.$and.map(c=>P(i,e,t,c)):Object.entries(r).map(([c,o])=>{var y,f;if(n.fields[c])return (o==null?void 0:o.$eq)!==void 0?t(`${e}.${c}`,o.$eq===null?"is":"=",o.$eq):(o==null?void 0:o.$in)!==void 0?t(`${e}.${c}`,"in",o.$in):(o==null?void 0:o.$not)!==void 0?((y=o==null?void 0:o.$not)==null?void 0:y.$in)!==void 0?t(`${e}.${c}`,"not in",o.$not.$in):((f=o==null?void 0:o.$not)==null?void 0:f.$eq)!==void 0?t(`${e}.${c}`,o.$not.$eq===null?"is not":"!=",o.$not.$eq):t(`${e}.${c}`,o.$not===null?"is not":"!=",o.$not):(o==null?void 0:o.$gt)!==void 0?t(`${e}.${c}`,">",o.$gt):(o==null?void 0:o.$gte)!==void 0?t(`${e}.${c}`,">=",o.$gte):(o==null?void 0:o.$lt)!==void 0?t(`${e}.${c}`,"<",o.$lt):(o==null?void 0:o.$lte)!==void 0?t(`${e}.${c}`,"<=",o.$lte):t(`${e}.${c}`,o===null?"is":"=",o);if(n.relations[c]){let u=n.relations[c],d=u.entity.name;u.type==="one"?"id":u.foreignColumn;u.type==="one"?u.relationalColumn:"id";return P(i,d,t,o)}return null}).filter(Boolean))}function Ve(i,e,t,r){let n=i[e];if(!n)throw new Error("Resource not found");if(!r)return t;for(let a of Object.keys(r)){if(!n.relations[a])continue;let s=n.relations[a],c=s.entity.name,o=s.type==="one"?"id":s.foreignColumn,y=s.type==="one"?s.relationalColumn:"id";t=t.leftJoin(c,`${c}.${o}`,`${e}.${y}`);}return t}function se(i,e,t,r){return !r||Object.keys(r).length===0?t:(t=Ve(i,e,t,r),t.where(n=>P(i,e,n,r)))}function k(i,e,t,r){if(!r)return t;if(!i)throw new Error("Schema not initialized");let n=i[e];if(!n)throw new Error(`Resource not found: ${e}`);for(let a of Object.keys(r)){if(!n.relations[a])throw new Error(`Relation ${a} not found in resource ${e}`);let s=n.relations[a],c=s.entity.name,o=s.type==="one"?"id":s.foreignColumn,y=s.type==="one"?s.relationalColumn:"id",f=s.type==="one"?jsonObjectFrom:jsonArrayFrom;t=t.select(u=>f(u.selectFrom(c).selectAll(c).whereRef(`${c}.${o}`,"=",`${e}.${y}`).select(d=>jsonObjectFrom(d.selectFrom(`${c}_meta`).selectAll(`${c}_meta`).whereRef(`${c}_meta.id`,"=",`${c}.id`)).as("_meta"))).as(a));}return t}var F=class i extends ${db;schema;constructor(e,t){super(),this.isKyselyLike(e)?this.db=e:this.db=new Kysely({dialect:new PostgresDialect({pool:e})}),this.schema=t,this.rawInsert=this.rawInsert.bind(this),this.rawUpdate=this.rawUpdate.bind(this);}async updateSchema(e){this.schema=e;let t=await this.db.introspection.getTables();for(let[r,n]of Object.entries(e)){let a=t.find(o=>o.name===r);a||await this.db.schema.createTable(r).ifNotExists().execute();let s=`${r}_meta`,c=t.find(o=>o.name===s);c||await this.db.schema.createTable(s).ifNotExists().execute();for(let[o,y]of Object.entries(n.fields)){let f=a==null?void 0:a.columns.find(p=>p.name===o),u=y.getStorageFieldType();f?f.dataType!==u.type&&console.error("Column type mismatch:",o,"expected to have type:",u.type,"but has type:",f.dataType):(await this.db.schema.alterTable(r).addColumn(o,u.type,p=>{let l=p;return u.unique&&(l=l.unique()),u.nullable||(l=l.notNull()),u.references&&(l=l.references(u.references)),u.primary&&(l=l.primaryKey()),u.default!==void 0&&(l=l.defaultTo(u.default)),l}).execute().catch(p=>{throw console.error("Error adding column",o,p),p}),u.index&&await this.db.schema.createIndex(`${r}_${o}_index`).on(r).column(o).execute().catch(p=>{})),(c==null?void 0:c.columns.find(p=>p.name===o))||await this.db.schema.alterTable(s).addColumn(o,"varchar",p=>{let l=p;return u.primary&&(l=l.primaryKey().references(`${r}.${o}`)),l}).execute();}}}async rawFindById(e,t,r){if(!this.schema)throw new Error("Schema not initialized");let n=await this.db.selectFrom(e).where("id","=",t).selectAll(e).select(s=>jsonObjectFrom(s.selectFrom(`${e}_meta`).selectAll(`${e}_meta`).whereRef(`${e}_meta.id`,"=",`${e}.id`)).as("_meta"));n=k(this.schema,e,n,r);let a=await n.executeTakeFirst();if(a)return this.convertToMaterializedLiveType(a)}async findOne(e,t,r$1){let n=await this.rawFindById(e.name,t,r$1==null?void 0:r$1.include);if(n)return r(n)}async rawFind(e,t,r){if(!this.schema)throw new Error("Schema not initialized");let n=this.db.selectFrom(e).selectAll(e).select(o=>jsonObjectFrom(o.selectFrom(`${e}_meta`).selectAll(`${e}_meta`).whereRef(`${e}_meta.id`,"=",`${e}.id`)).as("_meta"));n=se(this.schema,e,n,t),n=k(this.schema,e,n,r);let a=await n.execute(),s=Object.fromEntries(a.map(o=>{let{id:y,...f}=o;return [y,f]}));return Object.keys(s).length===0?{}:Object.entries(s).reduce((o,[y,f])=>(o[y]=this.convertToMaterializedLiveType(f),o),{})}async find(e,t){let r$1=await this.rawFind(e.name,t==null?void 0:t.where,t==null?void 0:t.include);return Object.fromEntries(Object.entries(r$1).map(([n,a])=>[n,r(a)]))}async rawInsert(e,t,r){var s;let n={},a={};for(let[c,o]of Object.entries(r.value)){let y=(s=o._meta)==null?void 0:s.timestamp;y&&(n[c]=o.value,a[c]=y);}return await this.db.insertInto(e).values({...n,id:t}).execute().then(()=>{this.db.insertInto(`${e}_meta`).values({...a,id:t}).execute();}),r}async rawUpdate(e,t,r){var s;let n={},a={};for(let[c,o]of Object.entries(r.value)){let y=(s=o._meta)==null?void 0:s.timestamp;y&&(n[c]=o.value,a[c]=y);}return await Promise.all([this.db.updateTable(e).set(n).where("id","=",t).execute(),this.db.insertInto(`${e}_meta`).values({...a,id:t}).onConflict(c=>c.column("id").doUpdateSet(a)).execute()]),r}async transaction(e){if(!this.schema)throw new Error("Schema not initialized");if(this.db.isTransaction){let r=Math.random().toString(36).substring(2,15),n=await this.db.savepoint(r).execute();try{return await e({trx:this,commit:()=>n.releaseSavepoint(r).execute().then(()=>{}),rollback:()=>n.rollbackToSavepoint(r).execute().then(()=>{})}).then(a=>n.isCommitted||n.isRolledBack?a:n.releaseSavepoint(r).execute().then(()=>a))}catch(a){throw await n.rollbackToSavepoint(r).execute().catch(()=>{}),a}}let t=await this.db.startTransaction().execute();try{return await e({trx:new i(t,this.schema),commit:()=>t.commit().execute(),rollback:()=>t.rollback().execute()}).then(r=>t.isCommitted||t.isRolledBack?r:t.commit().execute().then(()=>r))}catch(r){throw await t.rollback().execute(),r}}convertToMaterializedLiveType(e){return {value:Object.entries(e).reduce((t,[r,n])=>{var a,s,c;return r==="_meta"||(r==="id"?t[r]={value:n}:Array.isArray(n)?t[r]={value:n.map(o=>this.convertToMaterializedLiveType(o)),_meta:{timestamp:(a=e==null?void 0:e._meta)==null?void 0:a[r]}}:typeof n=="object"&&n!==null&&!(n instanceof Date)?t[r]={...this.convertToMaterializedLiveType(n),_meta:{timestamp:(s=e==null?void 0:e._meta)==null?void 0:s[r]}}:t[r]={value:n,_meta:{timestamp:(c=e==null?void 0:e._meta)==null?void 0:c[r]}}),t},{})}}isKyselyLike(e){if(e instanceof Kysely)return true;if(!e||typeof e!="object")return false;let t=e,r=typeof t.selectFrom=="function",n=typeof t.startTransaction=="function",a=typeof t.savepoint=="function",s=typeof t.isTransaction=="boolean"||typeof t.isTransaction=="function";return r&&n||a&&s}};var q=class i{router;storage;schema;middlewares=new Set;contextProvider;mutationSubscriptions=new Set;constructor(e){var t;this.router=e.router,this.storage=e.storage,this.schema=e.schema,(t=e.middlewares)==null||t.forEach(r=>{this.middlewares.add(r);}),this.storage.updateSchema(this.schema),this.contextProvider=e.contextProvider;}static create(e){return new i(e)}subscribeToMutations(e){return this.mutationSubscriptions.add(e),()=>{this.mutationSubscriptions.delete(e);}}async handleRequest(e){if(!this.router.routes[e.req.resourceName])throw new Error("Invalid resource");let t=await Array.from(this.middlewares.values()).reduceRight((r,n)=>a=>n({req:a,next:r}),async r=>this.router.routes[e.req.resourceName].handleRequest({req:r,db:this.storage,schema:this.schema}))(e.req);return t&&e.req.type==="MUTATE"&&t.acceptedValues&&Object.keys(t.acceptedValues).length>0&&(e.req.procedure==="INSERT"||e.req.procedure==="UPDATE")&&this.mutationSubscriptions.forEach(r=>{r({id:e.req.context.messageId,type:"MUTATE",resource:e.req.resourceName,payload:t.acceptedValues??{},resourceId:e.req.resourceId,procedure:e.req.procedure});}),t}use(e){return this.middlewares.add(e),this}context(e){return this.contextProvider=e,this}},kt=q.create;
|
|
2
2
|
export{_ as Route,V as RouteFactory,D as Router,F as SQLStorage,q as Server,$ as Storage,Tt as expressAdapter,Et as routeFactory,Mt as router,kt as server};
|