remult 0.19.2 → 0.20.0-exp.1

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.
Files changed (45) hide show
  1. package/esm/graphql.d.ts +1 -1
  2. package/esm/remult-express.d.ts +1 -1
  3. package/esm/remult-express.js +3 -1
  4. package/esm/remult-fastify.d.ts +1 -1
  5. package/esm/remult-fastify.js +3 -1
  6. package/esm/remult-fresh.d.ts +3 -3
  7. package/esm/remult-fresh.js +4 -2
  8. package/esm/remult-next.d.ts +1 -1
  9. package/esm/remult-next.js +3 -1
  10. package/esm/remult-svletekit.d.ts +3 -0
  11. package/esm/remult-svletekit.js +83 -0
  12. package/esm/server/expressBridge.d.ts +13 -10
  13. package/esm/server/expressBridge.js +57 -52
  14. package/esm/server/index.d.ts +2 -2
  15. package/esm/server/index.js +2 -2
  16. package/esm/src/data-api.d.ts +2 -2
  17. package/esm/src/live-query/SubscriptionServer.js +3 -3
  18. package/esm/src/remult3/RepositoryImplementation.js +2 -5
  19. package/esm/src/shared-tests/db-tests.db-tests.js +8 -0
  20. package/esm/src/tests/testHelper.spec.js +2 -2
  21. package/esm/src/valueConverters.d.ts +1 -0
  22. package/esm/src/valueConverters.js +15 -0
  23. package/graphql.d.ts +1 -1
  24. package/package.json +9 -1
  25. package/remult-express.d.ts +1 -1
  26. package/remult-express.js +3 -1
  27. package/remult-fastify.d.ts +1 -1
  28. package/remult-fastify.js +3 -1
  29. package/remult-fresh.d.ts +3 -3
  30. package/remult-fresh.js +4 -2
  31. package/remult-next.d.ts +1 -1
  32. package/remult-next.js +3 -1
  33. package/remult-svletekit.d.ts +3 -0
  34. package/remult-svletekit.js +136 -0
  35. package/server/expressBridge.d.ts +13 -10
  36. package/server/expressBridge.js +145 -113
  37. package/server/index.d.ts +2 -2
  38. package/server/index.js +2 -2
  39. package/src/data-api.d.ts +2 -2
  40. package/src/live-query/SubscriptionServer.js +3 -3
  41. package/src/remult3/RepositoryImplementation.js +2 -5
  42. package/src/shared-tests/db-tests.db-tests.js +20 -0
  43. package/src/tests/testHelper.spec.js +8 -2
  44. package/src/valueConverters.d.ts +1 -0
  45. package/src/valueConverters.js +15 -0
package/esm/graphql.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RemultServer } from "./server/expressBridge";
2
- export declare function remultGraphql(api: RemultServer): {
2
+ export declare function remultGraphql(api: RemultServer<any>): {
3
3
  rootValue: {};
4
4
  schema: string;
5
5
  };
@@ -3,4 +3,4 @@ import { RemultServer, RemultServerOptions } from './server/expressBridge';
3
3
  export declare function remultExpress(options?: RemultServerOptions<express.Request> & {
4
4
  bodyParser?: boolean;
5
5
  bodySizeLimit?: string;
6
- }): express.RequestHandler & RemultServer;
6
+ }): express.RequestHandler & RemultServer<express.Request>;
@@ -12,7 +12,9 @@ export function remultExpress(options) {
12
12
  app.use(express.json({ limit: options.bodySizeLimit }));
13
13
  app.use(express.urlencoded({ extended: true, limit: options.bodySizeLimit }));
14
14
  }
15
- const server = createRemultServer(options);
15
+ const server = createRemultServer(options, {
16
+ buildGenericRequest: req => req
17
+ });
16
18
  server.registerRouter(app);
17
19
  return Object.assign(app, {
18
20
  getRemult: (req) => server.getRemult(req),
@@ -1,3 +1,3 @@
1
1
  import type { FastifyPluginCallback, FastifyRequest } from 'fastify';
2
2
  import { RemultServer, RemultServerOptions } from './server/expressBridge';
3
- export declare function remultFastify(options: RemultServerOptions<FastifyRequest>): FastifyPluginCallback & RemultServer;
3
+ export declare function remultFastify(options: RemultServerOptions<FastifyRequest>): FastifyPluginCallback & RemultServer<FastifyRequest>;
@@ -29,7 +29,9 @@ export function remultFastify(options) {
29
29
  };
30
30
  return response;
31
31
  }
32
- const api = createRemultServer(options);
32
+ const api = createRemultServer(options, {
33
+ buildGenericRequest: req => req
34
+ });
33
35
  const pluginFunction = async (instance, op) => {
34
36
  //@ts-ignore
35
37
  let fastifyRouter = {
@@ -1,8 +1,8 @@
1
- import { RemultServerOptions, GenericRequest } from "./server/expressBridge";
1
+ import { RemultServerOptions } from "./server/expressBridge";
2
2
  import { Remult } from "./src/context";
3
- export declare function remultFresh<RequestType extends GenericRequest>(options: RemultServerOptions<RequestType>, response: FreshResponse): RemultFresh;
3
+ export declare function remultFresh(options: RemultServerOptions<FreshRequest>, response: FreshResponse): RemultFresh;
4
4
  export interface RemultFresh {
5
- getRemult(req: GenericRequest): Promise<Remult>;
5
+ getRemult(req: FreshRequest): Promise<Remult>;
6
6
  openApiDoc(options: {
7
7
  title: string;
8
8
  }): any;
@@ -1,6 +1,8 @@
1
1
  import { createRemultServerCore } from "./server/expressBridge";
2
2
  export function remultFresh(options, response) {
3
- const server = createRemultServerCore(options);
3
+ const server = createRemultServerCore(options, {
4
+ buildGenericRequest: r => r
5
+ });
4
6
  return {
5
7
  getRemult: r => server.getRemult(r),
6
8
  openApiDoc: x => server.openApiDoc(x),
@@ -17,7 +19,7 @@ export function remultFresh(options, response) {
17
19
  break;
18
20
  }
19
21
  let init = {};
20
- const res = await server.handle(theReq);
22
+ const res = await server.handle(req);
21
23
  if (res) {
22
24
  init.status = res.statusCode;
23
25
  if (res.data) {
@@ -2,7 +2,7 @@
2
2
  import type { GetServerSideProps, NextApiRequest, PreviewData, NextApiHandler } from "next";
3
3
  import type { ParsedUrlQuery } from "querystring";
4
4
  import { RemultServer, RemultServerOptions } from "./server";
5
- export declare function remultNext(options?: RemultServerOptions<NextApiRequest>): RemultServer & NextApiHandler & {
5
+ export declare function remultNext(options?: RemultServerOptions<NextApiRequest>): RemultServer<NextApiRequest> & NextApiHandler & {
6
6
  getServerSideProps<P extends {
7
7
  [key: string]: any;
8
8
  } = {
@@ -1,6 +1,8 @@
1
1
  import { createRemultServer } from "./server";
2
2
  export function remultNext(options) {
3
- let result = createRemultServer(options);
3
+ let result = createRemultServer(options, {
4
+ buildGenericRequest: req => req
5
+ });
4
6
  return Object.assign((req, res) => result.handle(req, res), result, {
5
7
  getRemult: (...args) => result.getRemult(...args),
6
8
  handle: (...args) => result.handle(...args),
@@ -0,0 +1,3 @@
1
+ import type { RequestEvent, Handle } from '@sveltejs/kit';
2
+ import { RemultServer, RemultServerOptions } from './server';
3
+ export declare function remultSveltekit(options?: RemultServerOptions<RequestEvent>): RemultServer<RequestEvent> & Handle;
@@ -0,0 +1,83 @@
1
+ import { createRemultServer } from './server';
2
+ export function remultSveltekit(options) {
3
+ let result = createRemultServer(options, {
4
+ buildGenericRequest: event => ({
5
+ url: event.request.url,
6
+ method: event.request.method,
7
+ body: event.locals["_tempJson"],
8
+ on: (e, do1) => {
9
+ if (e === 'close') {
10
+ event.locals["_tempOnClose"] = do1;
11
+ }
12
+ }
13
+ })
14
+ });
15
+ const handler = async ({ event, resolve }) => {
16
+ if (event.url.pathname.startsWith(options.rootPath)) {
17
+ let json = {};
18
+ try {
19
+ if (event.request.method == 'POST' || event.request.method == 'PUT') {
20
+ json = await event.request.json();
21
+ }
22
+ }
23
+ catch (error) {
24
+ console.log(error);
25
+ }
26
+ let sseResponse = undefined;
27
+ event.locals["_tempOnClose"] = () => { };
28
+ const response = {
29
+ end: () => { },
30
+ json: () => { },
31
+ status: () => {
32
+ return response;
33
+ },
34
+ write: () => { },
35
+ writeHead: (status, headers) => {
36
+ if (status === 200 && headers) {
37
+ const contentType = headers['Content-Type'];
38
+ if (contentType === 'text/event-stream') {
39
+ const messages = [];
40
+ response.write = (x) => messages.push(x);
41
+ const stream = new ReadableStream({
42
+ start: (controller) => {
43
+ for (const message of messages) {
44
+ controller.enqueue(message);
45
+ }
46
+ response.write = (data) => {
47
+ controller.enqueue(data);
48
+ };
49
+ },
50
+ cancel: () => {
51
+ response.write = () => { };
52
+ event.locals["_tempOnClose"]();
53
+ }
54
+ });
55
+ sseResponse = new Response(stream, { headers });
56
+ }
57
+ }
58
+ }
59
+ };
60
+ event.locals["_tempJson"] = json;
61
+ const responseFromRemultHandler = await result.handle(event, response);
62
+ if (sseResponse !== undefined) {
63
+ return sseResponse;
64
+ }
65
+ if (responseFromRemultHandler) {
66
+ return new Response(JSON.stringify(responseFromRemultHandler.data), {
67
+ status: responseFromRemultHandler.statusCode
68
+ });
69
+ }
70
+ }
71
+ return new Promise((res) => {
72
+ result.withRemult(event, undefined, async () => {
73
+ res(await resolve(event));
74
+ });
75
+ });
76
+ };
77
+ return Object.assign(handler, {
78
+ getRemult: (req) => result.getRemult(req),
79
+ openApiDoc: (options) => result.openApiDoc(options),
80
+ registerRouter: x => result.registerRouter(x),
81
+ withRemult: (...args) => result.withRemult(...args)
82
+ });
83
+ }
@@ -5,7 +5,7 @@ import { ClassType } from '../classType';
5
5
  import { Repository } from '../src/remult3';
6
6
  import { IdEntity } from '../src/id-entity';
7
7
  import { LiveQueryStorage, SubscriptionServer } from '../src/live-query/SubscriptionServer';
8
- export interface RemultServerOptions<RequestType extends GenericRequest> {
8
+ export interface RemultServerOptions<RequestType> {
9
9
  /**Entities to use for the api */
10
10
  entities?: ClassType<any>[];
11
11
  /**Controller to use for the api */
@@ -41,10 +41,10 @@ export interface RemultServerOptions<RequestType extends GenericRequest> {
41
41
  subscriptionServer?: SubscriptionServer;
42
42
  /** A storage to use to store live queries, relevant mostly for serverless scenarios or larger scales */
43
43
  liveQueryStorage?: LiveQueryStorage;
44
- /** Used to store the relevent request info for re running a live query */
45
- requestSerializer?: {
46
- toJson: (request: RequestType) => any;
47
- fromJson: (request: any) => RequestType;
44
+ /** Used to store the context relevant info for re running a live query */
45
+ contextSerializer?: {
46
+ serialize(remult: Remult): Promise<any>;
47
+ deserialize(json: any, remult: Remult): Promise<void>;
48
48
  };
49
49
  /** Storage to use for backend methods that use queue */
50
50
  queueStorage?: QueueStorage;
@@ -53,21 +53,21 @@ export interface InitRequestOptions {
53
53
  liveQueryStorage: LiveQueryStorage;
54
54
  readonly remult: Remult;
55
55
  }
56
- export declare function createRemultServerCore<RequestType extends GenericRequest = GenericRequest>(options?: RemultServerOptions<RequestType>): RemultServer;
56
+ export declare function createRemultServerCore<RequestType>(options: RemultServerOptions<RequestType>, serverCoreOptions: ServerCoreOptions<RequestType>): RemultServer<RequestType>;
57
57
  export declare type GenericRequestHandler = (req: GenericRequest, res: GenericResponse, next: VoidFunction) => void;
58
58
  export interface ServerHandleResponse {
59
59
  data?: any;
60
60
  statusCode: number;
61
61
  }
62
- export interface RemultServer {
63
- getRemult(req: GenericRequest): Promise<Remult>;
62
+ export interface RemultServer<RequestType> {
63
+ getRemult(req: RequestType): Promise<Remult>;
64
64
  openApiDoc(options: {
65
65
  title: string;
66
66
  version?: string;
67
67
  }): any;
68
68
  registerRouter(r: GenericRouter): void;
69
- handle(req: GenericRequest, gRes?: GenericResponse): Promise<ServerHandleResponse | undefined>;
70
- withRemult(req: GenericRequest, res: GenericResponse, next: VoidFunction): any;
69
+ handle(req: RequestType, gRes?: GenericResponse): Promise<ServerHandleResponse | undefined>;
70
+ withRemult(req: RequestType, res: GenericResponse, next: VoidFunction): any;
71
71
  }
72
72
  export declare type GenericRouter = {
73
73
  route(path: string): SpecificRoute;
@@ -128,3 +128,6 @@ export declare class JobsInQueueEntity extends IdEntity {
128
128
  error: boolean;
129
129
  progress: number;
130
130
  }
131
+ export interface ServerCoreOptions<RequestType> {
132
+ buildGenericRequest(req: RequestType): GenericRequest;
133
+ }
@@ -10,7 +10,7 @@ import { liveQueryKeepAliveRoute, streamUrl } from '../src/live-query/Subscripti
10
10
  import { initDataProvider } from './initDataProvider';
11
11
  import { SseSubscriptionServer } from "../SseSubscriptionServer";
12
12
  ;
13
- export function createRemultServerCore(options) {
13
+ export function createRemultServerCore(options, serverCoreOptions) {
14
14
  if (!options) {
15
15
  options = {};
16
16
  }
@@ -63,23 +63,6 @@ export function createRemultServerCore(options) {
63
63
  });
64
64
  return dp;
65
65
  });
66
- if (!options.requestSerializer) {
67
- options.requestSerializer = {
68
- toJson: x => {
69
- const r = {
70
- url: x.url
71
- };
72
- for (const key of ['session', 'auth', 'user']) {
73
- if (x[key])
74
- r[key] = x[key];
75
- }
76
- return r;
77
- },
78
- fromJson: x => {
79
- return x;
80
- }
81
- };
82
- }
83
66
  {
84
67
  let allControllers = [];
85
68
  if (!options.entities)
@@ -93,7 +76,7 @@ export function createRemultServerCore(options) {
93
76
  if (options.rootPath === undefined)
94
77
  options.rootPath = '/api';
95
78
  actionInfo.runningOnServer = true;
96
- let bridge = new RemultServerImplementation(new inProcessQueueHandler(options.queueStorage), options, dataProvider);
79
+ let bridge = new RemultServerImplementation(new inProcessQueueHandler(options.queueStorage), options, dataProvider, serverCoreOptions);
97
80
  return bridge;
98
81
  }
99
82
  ;
@@ -129,20 +112,22 @@ export class RemultAsyncLocalStorage {
129
112
  RemultAsyncLocalStorage.instance = new RemultAsyncLocalStorage(undefined);
130
113
  /* @internal*/
131
114
  export class RemultServerImplementation {
132
- constructor(queue, options, dataProvider) {
115
+ constructor(queue, options, dataProvider, coreOptions) {
133
116
  this.queue = queue;
134
117
  this.options = options;
135
118
  this.dataProvider = dataProvider;
119
+ this.coreOptions = coreOptions;
136
120
  this.liveQueryStorage = new InMemoryLiveQueryStorage();
137
- this.runWithRequest = async (req, entityKey, what) => {
121
+ this.runWithSerializedJsonContextData = async (jsonContextData, entityKey, what) => {
138
122
  for (const e of this.options.entities) {
139
123
  let key = getEntityKey(e);
140
124
  if (key === entityKey) {
141
- await new Promise((result) => {
142
- this.withRemult(this.options.requestSerializer.fromJson(req), undefined, async () => {
143
- await what(remult.repo(e));
144
- result({});
145
- });
125
+ await this.runWithRemult(async (remult) => {
126
+ remult.user = jsonContextData.user;
127
+ if (this.options.contextSerializer) {
128
+ await this.options.contextSerializer.deserialize(jsonContextData, remult);
129
+ }
130
+ await what(remult.repo(e));
146
131
  });
147
132
  return;
148
133
  }
@@ -164,7 +149,7 @@ export class RemultServerImplementation {
164
149
  }
165
150
  getRouteImpl() {
166
151
  if (!this.routeImpl) {
167
- this.routeImpl = new RouteImplementation();
152
+ this.routeImpl = new RouteImplementation(this.coreOptions);
168
153
  this.registerRouter(this.routeImpl);
169
154
  }
170
155
  return this.routeImpl;
@@ -230,14 +215,24 @@ export class RemultServerImplementation {
230
215
  }, r);
231
216
  });
232
217
  }
218
+ async serializeContext(remult) {
219
+ let result = {
220
+ user: remult.user,
221
+ context: undefined
222
+ };
223
+ if (this.options.contextSerializer) {
224
+ result.context = await this.options.contextSerializer.serialize(remult);
225
+ }
226
+ return result;
227
+ }
233
228
  add(key, dataApiFactory, r) {
234
229
  let myRoute = this.options.rootPath + '/' + key;
235
230
  if (this.options.logApiEndPoints)
236
231
  console.info("[remult] " + myRoute);
237
232
  r.route(myRoute)
238
- .get(this.process((c, req, res, orig) => dataApiFactory(c).httpGet(res, req, () => this.options.requestSerializer.toJson(orig)))).put(this.process(async (c, req, res, orig) => dataApiFactory(c).put(res, '', orig.body)))
233
+ .get(this.process((c, req, res, orig) => dataApiFactory(c).httpGet(res, req, () => this.serializeContext(c)))).put(this.process(async (c, req, res, orig) => dataApiFactory(c).put(res, '', orig.body)))
239
234
  .delete(this.process(async (c, req, res, orig) => dataApiFactory(c).delete(res, '')))
240
- .post(this.process(async (c, req, res, orig) => dataApiFactory(c).httpPost(res, req, orig.body, () => this.options.requestSerializer.toJson(orig))));
235
+ .post(this.process(async (c, req, res, orig) => dataApiFactory(c).httpPost(res, req, orig.body, () => this.serializeContext(c))));
241
236
  r.route(myRoute + '/:id')
242
237
  //@ts-ignore
243
238
  .get(this.process(async (c, req, res, orig) => dataApiFactory(c).get(res, orig.params.id)))
@@ -246,29 +241,38 @@ export class RemultServerImplementation {
246
241
  //@ts-ignore
247
242
  .delete(this.process(async (c, req, res, orig) => dataApiFactory(c).delete(res, orig.params.id)));
248
243
  }
244
+ async runWithRemult(what) {
245
+ let remult = new Remult();
246
+ remult.liveQueryPublisher = new LiveQueryPublisher(() => remult.subscriptionServer, () => remult.liveQueryStorage, this.runWithSerializedJsonContextData);
247
+ remult.dataProvider = (await this.dataProvider);
248
+ remult.subscriptionServer = this.subscriptionServer;
249
+ remult.liveQueryStorage = this.liveQueryStorage;
250
+ await new Promise(res => {
251
+ RemultAsyncLocalStorage.instance.run(remult, async () => {
252
+ res(await what(remult));
253
+ });
254
+ });
255
+ }
249
256
  process(what) {
250
257
  return async (req, origRes) => {
251
258
  let myReq = new ExpressRequestBridgeToDataApiRequest(req);
252
259
  let myRes = new ExpressResponseBridgeToDataApiResponse(origRes, req);
253
- let remult = new Remult();
254
- remult.liveQueryPublisher = new LiveQueryPublisher(() => remult.subscriptionServer, () => remult.liveQueryStorage, this.runWithRequest);
255
- remult.dataProvider = (await this.dataProvider);
256
- remult.subscriptionServer = this.subscriptionServer;
257
- remult.liveQueryStorage = this.liveQueryStorage;
258
- await new Promise(res => {
259
- RemultAsyncLocalStorage.instance.run(remult, async () => {
260
- if (req) {
261
- let user;
262
- if (this.options.getUser)
263
- user = await this.options.getUser(req);
264
- else {
265
- user = req['user'];
266
- if (!user)
267
- user = req['auth'];
268
- }
269
- if (user)
270
- remult.user = (user);
260
+ await this.runWithRemult(async (remult) => {
261
+ remult.liveQueryPublisher = new LiveQueryPublisher(() => remult.subscriptionServer, () => remult.liveQueryStorage, this.runWithSerializedJsonContextData);
262
+ remult.dataProvider = (await this.dataProvider);
263
+ remult.subscriptionServer = this.subscriptionServer;
264
+ remult.liveQueryStorage = this.liveQueryStorage;
265
+ if (req) {
266
+ let user;
267
+ if (this.options.getUser)
268
+ user = await this.options.getUser(req);
269
+ else {
270
+ user = req['user'];
271
+ if (!user)
272
+ user = req['auth'];
271
273
  }
274
+ if (user)
275
+ remult.user = (user);
272
276
  if (this.options.initRequest) {
273
277
  await this.options.initRequest(req, {
274
278
  remult,
@@ -280,9 +284,8 @@ export class RemultServerImplementation {
280
284
  }
281
285
  });
282
286
  }
283
- await what(remult, myReq, myRes, req, origRes);
284
- res({});
285
- });
287
+ }
288
+ await what(remult, myReq, myRes, req, origRes);
286
289
  });
287
290
  };
288
291
  }
@@ -776,7 +779,8 @@ export class EntityQueueStorage {
776
779
  }
777
780
  }
778
781
  class RouteImplementation {
779
- constructor() {
782
+ constructor(coreOptions) {
783
+ this.coreOptions = coreOptions;
780
784
  this.map = new Map();
781
785
  }
782
786
  route(path) {
@@ -846,7 +850,8 @@ class RouteImplementation {
846
850
  this.middleware(req, response, () => res(undefined));
847
851
  });
848
852
  }
849
- middleware(req, res, next) {
853
+ middleware(origReq, res, next) {
854
+ const req = this.coreOptions.buildGenericRequest(origReq);
850
855
  let theUrl = req.url;
851
856
  if (theUrl.startsWith('/')) //next sends a partial url '/api/tasks' and not the full url
852
857
  theUrl = 'http://stam' + theUrl;
@@ -1,6 +1,6 @@
1
- import { GenericRequest, RemultServer, RemultServerOptions } from './expressBridge';
1
+ import { RemultServer, RemultServerOptions, ServerCoreOptions } from './expressBridge';
2
2
  export { queuedJobInfo, QueueStorage, GenericRequest, GenericRequestHandler, GenericResponse, GenericRouter, RemultServerOptions, SpecificRoute, RemultServer, InitRequestOptions } from './expressBridge';
3
3
  export { JsonEntityFileStorage, JsonFileDataProvider } from './JsonEntityFileStorage';
4
4
  export { DataProviderLiveQueryStorage } from '../live-query/data-provider-live-query-storage';
5
5
  export { SseSubscriptionServer } from '../SseSubscriptionServer';
6
- export declare function createRemultServer<RequestType extends GenericRequest = GenericRequest>(options?: RemultServerOptions<RequestType>): RemultServer;
6
+ export declare function createRemultServer<RequestType>(options: RemultServerOptions<RequestType>, serverCoreOptions?: ServerCoreOptions<RequestType>): RemultServer<RequestType>;
@@ -3,7 +3,7 @@ import { initAsyncHooks } from './initAsyncHooks';
3
3
  export { JsonEntityFileStorage, JsonFileDataProvider } from './JsonEntityFileStorage';
4
4
  export { DataProviderLiveQueryStorage } from '../live-query/data-provider-live-query-storage';
5
5
  export { SseSubscriptionServer } from '../SseSubscriptionServer';
6
- export function createRemultServer(options) {
6
+ export function createRemultServer(options, serverCoreOptions) {
7
7
  initAsyncHooks();
8
- return createRemultServerCore(options);
8
+ return createRemultServerCore(options, serverCoreOptions || { buildGenericRequest: req => req });
9
9
  }
@@ -5,8 +5,8 @@ export declare class DataApi<T = any> {
5
5
  private repository;
6
6
  private remult;
7
7
  constructor(repository: Repository<T>, remult: Remult);
8
- httpGet(res: DataApiResponse, req: DataApiRequest, serializeRequest: () => any): Promise<void>;
9
- httpPost(res: DataApiResponse, req: DataApiRequest, body: any, serializeRequest: () => any): Promise<void>;
8
+ httpGet(res: DataApiResponse, req: DataApiRequest, serializeRequest: () => Promise<any>): Promise<void>;
9
+ httpPost(res: DataApiResponse, req: DataApiRequest, body: any, serializeRequest: () => Promise<any>): Promise<void>;
10
10
  static defaultGetLimit: number;
11
11
  get(response: DataApiResponse, id: any): Promise<void>;
12
12
  count(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
@@ -1,10 +1,10 @@
1
1
  import { findOptionsFromJson } from '../data-providers/rest-data-provider';
2
2
  /* @internal*/
3
3
  export class LiveQueryPublisher {
4
- constructor(subscriptionServer, liveQueryStorage, performWithRequest) {
4
+ constructor(subscriptionServer, liveQueryStorage, performWithContext) {
5
5
  this.subscriptionServer = subscriptionServer;
6
6
  this.liveQueryStorage = liveQueryStorage;
7
- this.performWithRequest = performWithRequest;
7
+ this.performWithContext = performWithContext;
8
8
  this.debugFileSaver = (x) => { };
9
9
  }
10
10
  runPromise(p) { }
@@ -12,7 +12,7 @@ export class LiveQueryPublisher {
12
12
  //TODO 2 - optimize so that the user will get their messages first. Based on user id
13
13
  await (this.liveQueryStorage().forEach(entityKey, async ({ query: q, setData }) => {
14
14
  let query = { ...q.data };
15
- await this.performWithRequest(query.requestJson, entityKey, async (repo) => {
15
+ await this.performWithContext(query.requestJson, entityKey, async (repo) => {
16
16
  const messages = [];
17
17
  const currentItems = await repo.find(findOptionsFromJson(query.findOptionsJson, repo.metadata));
18
18
  const currentIds = currentItems.map(x => repo.getEntityRef(x).getId());
@@ -1259,7 +1259,7 @@ export class columnDefsImpl {
1259
1259
  get includedInApi() {
1260
1260
  if (this.options.includeInApi === undefined)
1261
1261
  return true;
1262
- return this.remult.isAllowed(this.options.includeInApi); //TODO - consolidate other code paths to go through here
1262
+ return this.remult.isAllowed(this.options.includeInApi); //TODO 2- consolidate other code paths to go through here
1263
1263
  }
1264
1264
  toInput(value, inputType) {
1265
1265
  return this.valueConverter.toInput(value, inputType);
@@ -1711,10 +1711,7 @@ export function decorateColumnSettings(settings, remult) {
1711
1711
  if (settings.valueType == String) {
1712
1712
  let x = settings;
1713
1713
  if (!settings.valueConverter)
1714
- x.valueConverter = {
1715
- toJson: x => x,
1716
- fromJson: x => x
1717
- };
1714
+ x.valueConverter = ValueConverters.String;
1718
1715
  }
1719
1716
  if (settings.valueType == Number) {
1720
1717
  let x = settings;
@@ -25,6 +25,14 @@ testAll("what", async ({ remult, createEntity }) => {
25
25
  await (await createEntity(stam)).create({ id: 1, title: 'noam' }).save();
26
26
  expect(await remult.repo(stam).count()).toBe(1);
27
27
  }, false);
28
+ testAll("data types", async ({ remult, createEntity }) => {
29
+ let r = await (await createEntity(stam)).create({
30
+ id: 1,
31
+ //@ts-ignore
32
+ title: 42
33
+ }).save();
34
+ expect(r.title).toEqual("42");
35
+ }, false);
28
36
  testAll("filter works on all db", async ({ createEntity }) => {
29
37
  let s = await entityWithValidations.create4RowsInDp(createEntity);
30
38
  expect((await s.find({ where: { myId: [1, 3] } })).length).toBe(2);
@@ -186,7 +186,7 @@ export function createMockHttpDataProvider(dataApi) {
186
186
  r.success = data => { result = data; };
187
187
  try {
188
188
  testConfiguration.restDbRunningOnServer = true;
189
- await dataApi.httpGet(r, urlToReq(url), () => "");
189
+ await dataApi.httpGet(r, urlToReq(url), async () => "");
190
190
  }
191
191
  finally {
192
192
  testConfiguration.restDbRunningOnServer = false;
@@ -200,7 +200,7 @@ export function createMockHttpDataProvider(dataApi) {
200
200
  r.success = data => { result = data; };
201
201
  try {
202
202
  testConfiguration.restDbRunningOnServer = true;
203
- await dataApi.httpPost(r, urlToReq(url), data, () => ({}));
203
+ await dataApi.httpPost(r, urlToReq(url), data, async () => ({}));
204
204
  }
205
205
  finally {
206
206
  testConfiguration.restDbRunningOnServer = false;
@@ -5,6 +5,7 @@ export declare class ValueConverters {
5
5
  static readonly DateOnlyString: ValueConverter<Date>;
6
6
  static readonly Boolean: ValueConverter<Boolean>;
7
7
  static readonly Number: ValueConverter<number>;
8
+ static readonly String: ValueConverter<String>;
8
9
  static readonly Integer: ValueConverter<number>;
9
10
  static readonly Default: Required<ValueConverter<any>>;
10
11
  static readonly JsonString: ValueConverter<any>;
@@ -141,6 +141,14 @@ ValueConverters.Number = {
141
141
  },
142
142
  inputType: InputTypes.number
143
143
  };
144
+ ValueConverters.String = {
145
+ fromDb: enforceString,
146
+ toDb: enforceString,
147
+ fromJson: enforceString,
148
+ toJson: enforceString,
149
+ fromInput: enforceString,
150
+ toInput: enforceString,
151
+ };
144
152
  ValueConverters.Integer = {
145
153
  ...ValueConverters.Number,
146
154
  toJson: value => {
@@ -180,3 +188,10 @@ ValueConverters.JsonValue = {
180
188
  toInput: x => ValueConverters.JsonString.toJson(x),
181
189
  fieldTypeInDb: 'json'
182
190
  };
191
+ function enforceString(value) {
192
+ if (value === null || value === undefined)
193
+ return value;
194
+ if (typeof (value) !== "string")
195
+ return value.toString();
196
+ return value;
197
+ }
package/graphql.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RemultServer } from "./server/expressBridge";
2
- export declare function remultGraphql(api: RemultServer): {
2
+ export declare function remultGraphql(api: RemultServer<any>): {
3
3
  rootValue: {};
4
4
  schema: string;
5
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.19.2",
3
+ "version": "0.20.0-exp.1",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -78,6 +78,14 @@
78
78
  },
79
79
  "import": "./esm/remult-fresh.js"
80
80
  },
81
+ "./remult-sveltekit": {
82
+ "require": "./remult-sveltekit.js",
83
+ "node": {
84
+ "require": "./remult-sveltekit.js",
85
+ "import": "./remult-sveltekit.js"
86
+ },
87
+ "import": "./esm/remult-sveltekit.js"
88
+ },
81
89
  "./postgres": {
82
90
  "require": "./postgres/index.js",
83
91
  "node": {
@@ -3,4 +3,4 @@ import { RemultServer, RemultServerOptions } from './server/expressBridge';
3
3
  export declare function remultExpress(options?: RemultServerOptions<express.Request> & {
4
4
  bodyParser?: boolean;
5
5
  bodySizeLimit?: string;
6
- }): express.RequestHandler & RemultServer;
6
+ }): express.RequestHandler & RemultServer<express.Request>;
package/remult-express.js CHANGED
@@ -16,7 +16,9 @@ function remultExpress(options) {
16
16
  app.use(express.json({ limit: options.bodySizeLimit }));
17
17
  app.use(express.urlencoded({ extended: true, limit: options.bodySizeLimit }));
18
18
  }
19
- var server = index_1.createRemultServer(options);
19
+ var server = index_1.createRemultServer(options, {
20
+ buildGenericRequest: function (req) { return req; }
21
+ });
20
22
  server.registerRouter(app);
21
23
  return Object.assign(app, {
22
24
  getRemult: function (req) { return server.getRemult(req); },
@@ -1,3 +1,3 @@
1
1
  import type { FastifyPluginCallback, FastifyRequest } from 'fastify';
2
2
  import { RemultServer, RemultServerOptions } from './server/expressBridge';
3
- export declare function remultFastify(options: RemultServerOptions<FastifyRequest>): FastifyPluginCallback & RemultServer;
3
+ export declare function remultFastify(options: RemultServerOptions<FastifyRequest>): FastifyPluginCallback & RemultServer<FastifyRequest>;