remult 0.15.4 → 0.16.0-exp.10

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 (43) hide show
  1. package/esm/index.d.ts +4 -2
  2. package/esm/index.js +3 -1
  3. package/esm/postgres/postgres-data-provider.js +2 -2
  4. package/esm/remult-express.js +2 -1
  5. package/esm/server/expressBridge.d.ts +1 -0
  6. package/esm/server/expressBridge.js +48 -20
  7. package/esm/src/backend-tests/test-http-server.backend-spec.js +13 -10
  8. package/esm/src/context.d.ts +18 -20
  9. package/esm/src/context.js +56 -70
  10. package/esm/src/data-providers/rest-data-provider.d.ts +4 -4
  11. package/esm/src/data-providers/rest-data-provider.js +20 -14
  12. package/esm/src/remult-proxy.d.ts +2 -0
  13. package/esm/src/remult-proxy.js +48 -0
  14. package/esm/src/remult3/RepositoryImplementation.d.ts +2 -1
  15. package/esm/src/remult3/RepositoryImplementation.js +5 -3
  16. package/esm/src/server-action.d.ts +8 -7
  17. package/esm/src/server-action.js +38 -32
  18. package/esm/src/shared-tests/db-tests-setup.js +1 -1
  19. package/esm/src/tests/createData.js +1 -1
  20. package/esm/src/tests/frontend-database-tests-setup.spec.js +3 -3
  21. package/esm/src/tests/testHelper.spec.js +17 -12
  22. package/index.d.ts +4 -2
  23. package/index.js +7 -3
  24. package/package.json +1 -1
  25. package/postgres/postgres-data-provider.js +2 -2
  26. package/remult-express.js +9 -1
  27. package/server/expressBridge.d.ts +1 -0
  28. package/server/expressBridge.js +82 -31
  29. package/src/backend-tests/test-http-server.backend-spec.js +11 -8
  30. package/src/context.d.ts +18 -20
  31. package/src/context.js +65 -89
  32. package/src/data-providers/rest-data-provider.d.ts +4 -4
  33. package/src/data-providers/rest-data-provider.js +21 -13
  34. package/src/remult-proxy.d.ts +2 -0
  35. package/src/remult-proxy.js +82 -0
  36. package/src/remult3/RepositoryImplementation.d.ts +2 -1
  37. package/src/remult3/RepositoryImplementation.js +5 -3
  38. package/src/server-action.d.ts +8 -7
  39. package/src/server-action.js +130 -119
  40. package/src/shared-tests/db-tests-setup.js +1 -1
  41. package/src/tests/createData.js +1 -1
  42. package/src/tests/frontend-database-tests-setup.spec.js +3 -3
  43. package/src/tests/testHelper.spec.js +19 -14
package/esm/index.d.ts CHANGED
@@ -8,10 +8,11 @@ export { RestDataProvider } from './src/data-providers/rest-data-provider';
8
8
  export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
9
9
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider';
10
10
  export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider';
11
- export { SqlDatabase } from './src/data-providers/sql-database';
11
+ export { SqlDatabase, } from './src/data-providers/sql-database';
12
+ export { CustomSqlFilterObject, CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
12
13
  export { JsonDataProvider, JsonEntityStorage } from './src/data-providers/json-data-provider';
13
14
  export { Controller, BackendMethodOptions, BackendMethod, ProgressListener } from './src/server-action';
14
- export { Allowed, Allow, Remult, isBackend, AllowedForInstance, EventDispatcher, EventSource, HttpProvider, Unobserve, UserInfo } from './src/context';
15
+ export { Allowed, Allow, Remult, RemultContext, ApiClient, isBackend, AllowedForInstance, EventDispatcher, EventSource, ExternalHttpProvider, Unobserve, UserInfo } from './src/context';
15
16
  export { IdEntity } from './src/id-entity';
16
17
  export { SortSegment, Sort } from './src/sort';
17
18
  export { OneToMany, CompoundIdField } from './src/column';
@@ -20,3 +21,4 @@ export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-b
20
21
  export { UrlBuilder } from './urlBuilder';
21
22
  export { Validators } from './src/validators';
22
23
  export { ValueConverters } from './src/valueConverters';
24
+ export { remult } from './src/remult-proxy';
package/esm/index.js CHANGED
@@ -6,7 +6,8 @@ export { RestDataProvider } from './src/data-providers/rest-data-provider'; //V
6
6
  export { InMemoryDataProvider } from './src/data-providers/in-memory-database'; //V
7
7
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider'; //V
8
8
  export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider'; //V
9
- export { SqlDatabase } from './src/data-providers/sql-database'; //V
9
+ export { SqlDatabase, } from './src/data-providers/sql-database'; //V
10
+ export { CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
10
11
  export { JsonDataProvider } from './src/data-providers/json-data-provider'; //V
11
12
  //export * from './src/data-api'; //reconsider if to make internal
12
13
  export { Controller, BackendMethod, ProgressListener } from './src/server-action';
@@ -19,3 +20,4 @@ export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-b
19
20
  export { UrlBuilder } from './urlBuilder';
20
21
  export { Validators } from './src/validators';
21
22
  export { ValueConverters } from './src/valueConverters';
23
+ export { remult } from './src/remult-proxy';
@@ -81,14 +81,14 @@ export async function createPostgresConnection(options) {
81
81
  }
82
82
  const db = new SqlDatabase(new PostgresDataProvider(new Pool(config)));
83
83
  let remult = new Remult();
84
- remult.setDataProvider(db);
84
+ remult.dataProvider = (db);
85
85
  if (options.autoCreateTables === undefined || options.autoCreateTables)
86
86
  await verifyStructureOfAllEntities(db, remult);
87
87
  return db;
88
88
  }
89
89
  export async function preparePostgresQueueStorage(sql) {
90
90
  let c = new Remult();
91
- c.setDataProvider(sql);
91
+ c.dataProvider = (sql);
92
92
  let JobsInQueueEntity = (await import('../server/expressBridge')).JobsInQueueEntity;
93
93
  let e = c.repo(JobsInQueueEntity);
94
94
  await new PostgresSchemaBuilder(sql).createIfNotExist(e.metadata);
@@ -17,6 +17,7 @@ export function remultExpress(options) {
17
17
  return Object.assign(app, {
18
18
  getRemult: (req) => server.getRemult(req),
19
19
  openApiDoc: (options) => server.openApiDoc(options),
20
- registerRouter: x => server.registerRouter(x)
20
+ registerRouter: x => server.registerRouter(x),
21
+ withRemultMiddleware: (...args) => server.withRemultMiddleware(...args)
21
22
  });
22
23
  }
@@ -33,6 +33,7 @@ export interface RemultServer {
33
33
  }): any;
34
34
  registerRouter(r: GenericRouter): void;
35
35
  handle(req: GenericRequest, gRes?: GenericResponse): Promise<ServerHandleResponse | undefined>;
36
+ withRemultMiddleware(req: GenericRequest, res: GenericResponse, next: VoidFunction): any;
36
37
  }
37
38
  export declare type GenericRouter = {
38
39
  route(path: string): SpecificRoute;
@@ -4,6 +4,8 @@ import { DataApi, serializeError } from '../src/data-api';
4
4
  import { allEntities, Remult } from '../src/context';
5
5
  import { Entity, Fields, getEntityKey } from '../src/remult3';
6
6
  import { IdEntity } from '../src/id-entity';
7
+ import { AsyncLocalStorage } from 'async_hooks';
8
+ import { remult } from '../src/remult-proxy';
7
9
  ;
8
10
  export function createRemultServer(options) {
9
11
  if (!options) {
@@ -32,7 +34,12 @@ export function createRemultServer(options) {
32
34
  if (options.initApi) {
33
35
  dataProvider = dataProvider.then(async (dp) => {
34
36
  var remult = new Remult(dp);
35
- await options.initApi(remult);
37
+ await new Promise((res) => {
38
+ remultObjectStorage.run(remult, async () => {
39
+ await options.initApi(remult);
40
+ res({});
41
+ });
42
+ });
36
43
  return dp;
37
44
  });
38
45
  }
@@ -47,12 +54,14 @@ export function createRemultServer(options) {
47
54
  options.controllers = allControllers;
48
55
  }
49
56
  if (options.rootPath === undefined)
50
- options.rootPath = Remult.apiBaseUrl;
57
+ options.rootPath = '/api';
51
58
  actionInfo.runningOnServer = true;
52
59
  let bridge = new RemultServerImplementation(new inProcessQueueHandler(options.queueStorage), options, dataProvider);
53
60
  return bridge;
54
61
  }
55
62
  ;
63
+ const remultObjectStorage = new AsyncLocalStorage();
64
+ let remultObjectStorageWasSetup = false;
56
65
  class RemultServerImplementation {
57
66
  constructor(queue, options, dataProvider) {
58
67
  this.queue = queue;
@@ -62,6 +71,19 @@ class RemultServerImplementation {
62
71
  this.hasQueue = false;
63
72
  /* internal */
64
73
  this.backendMethodsOpenApi = [];
74
+ if (!remultObjectStorageWasSetup) {
75
+ remultObjectStorageWasSetup = true;
76
+ remult.remultFactory = () => {
77
+ const r = remultObjectStorage.getStore();
78
+ if (r)
79
+ return r;
80
+ else
81
+ throw new Error("remult object was requested outside of a valid context, try running it within initApi or a remult request cycle");
82
+ };
83
+ }
84
+ }
85
+ withRemultMiddleware(req, res, next) {
86
+ this.process(async () => { next(); })(req, res);
65
87
  }
66
88
  handle(req, gRes) {
67
89
  if (!this.routeImpl) {
@@ -101,7 +123,8 @@ class RemultServerImplementation {
101
123
  else
102
124
  res.success(job.info);
103
125
  });
104
- }
126
+ },
127
+ doWork: undefined
105
128
  }, r);
106
129
  }
107
130
  this.options.entities.forEach(e => {
@@ -133,23 +156,28 @@ class RemultServerImplementation {
133
156
  let myReq = new ExpressRequestBridgeToDataApiRequest(req);
134
157
  let myRes = new ExpressResponseBridgeToDataApiResponse(res, req);
135
158
  let remult = new Remult();
136
- remult.setDataProvider(await this.dataProvider);
137
- if (req) {
138
- let user;
139
- if (this.options.getUser)
140
- user = await this.options.getUser(req);
141
- else {
142
- user = req['user'];
143
- if (!user)
144
- user = req['auth'];
145
- }
146
- if (user)
147
- remult.setUser(user);
148
- }
149
- if (this.options.initRequest) {
150
- await this.options.initRequest(remult, req);
151
- }
152
- what(remult, myReq, myRes, req);
159
+ remult.dataProvider = (await this.dataProvider);
160
+ await new Promise(res => {
161
+ remultObjectStorage.run(remult, async () => {
162
+ if (req) {
163
+ let user;
164
+ if (this.options.getUser)
165
+ user = await this.options.getUser(req);
166
+ else {
167
+ user = req['user'];
168
+ if (!user)
169
+ user = req['auth'];
170
+ }
171
+ if (user)
172
+ remult.user = (user);
173
+ }
174
+ if (this.options.initRequest) {
175
+ await this.options.initRequest(remult, req);
176
+ }
177
+ await what(remult, myReq, myRes, req);
178
+ res({});
179
+ });
180
+ });
153
181
  };
154
182
  }
155
183
  ;
@@ -1,13 +1,14 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import axios from 'axios';
3
3
  import { remultFresh } from '../../remult-fresh';
4
- import { HttpProviderBridgeToRestDataProviderHttpProvider, Remult } from '../context';
4
+ import { Remult } from '../context';
5
5
  import { InMemoryDataProvider } from '../data-providers/in-memory-database';
6
+ import { remult } from '../remult-proxy';
6
7
  import { Entity, Fields } from '../remult3';
7
- import { Action, BackendMethod } from '../server-action';
8
+ import { BackendMethod } from '../server-action';
8
9
  import { Categories } from '../tests/remult-3-entities';
9
- Remult.apiBaseUrl = 'http://localhost:3003/api';
10
- let path = Remult.apiBaseUrl + '/tasks';
10
+ remult.apiClient.url = 'http://localhost:3003/api';
11
+ let path = remult.apiClient.url + '/tasks';
11
12
  const environments = [
12
13
  // ["next", 3000],
13
14
  // ["nest", 3001],
@@ -21,8 +22,8 @@ const environments = [
21
22
  function test(name, test) {
22
23
  for (const [env, port] of environments) {
23
24
  const theTest = async () => {
24
- Remult.apiBaseUrl = `http://localhost:${port}/api`;
25
- path = Remult.apiBaseUrl + '/tasks';
25
+ remult.apiClient.url = `http://localhost:${port}/api`;
26
+ path = remult.apiClient.url + '/tasks';
26
27
  await test();
27
28
  };
28
29
  const testName = env + ` ${port}: ${name}`;
@@ -93,7 +94,7 @@ test("test http 201", async () => {
93
94
  });
94
95
  test("test regular api call", async () => {
95
96
  await create3Tasks();
96
- let result = await axios.get(Remult.apiBaseUrl + "/test");
97
+ let result = await axios.get(remult.apiClient.url + "/test");
97
98
  expect(result.data.result).toBe(3);
98
99
  });
99
100
  class FreshResponseTest {
@@ -106,9 +107,11 @@ class FreshResponseTest {
106
107
  }
107
108
  }
108
109
  it("test fresh", async () => {
109
- const api = remultFresh({ entities: [Categories],
110
+ const api = remultFresh({
111
+ entities: [Categories],
110
112
  dataProvider: new InMemoryDataProvider(),
111
- rootPath: '/api' }, FreshResponseTest);
113
+ rootPath: '/api'
114
+ }, FreshResponseTest);
112
115
  const r = await api.handle({
113
116
  url: '/api/Categories',
114
117
  json() {
@@ -158,7 +161,7 @@ Task = __decorate([
158
161
  export { Task };
159
162
  async function create3Tasks() {
160
163
  const remult = new Remult(axios);
161
- Action.provider = new HttpProviderBridgeToRestDataProviderHttpProvider(axios);
164
+ remult.apiClient.httpClient = axios;
162
165
  const taskRepo = remult.repo(Task);
163
166
  for (const task of await taskRepo.find()) {
164
167
  await taskRepo.delete(task);
@@ -1,7 +1,8 @@
1
1
  import { DataProvider, RestDataProviderHttpProvider } from "./data-interfaces";
2
+ import { RestDataProviderHttpProviderUsingFetch } from './data-providers/rest-data-provider';
2
3
  import { EntityMetadata, EntityRef, FindOptions, Repository } from "./remult3";
3
4
  import { ClassType } from "../classType";
4
- export interface HttpProvider {
5
+ export interface ExternalHttpProvider {
5
6
  post(url: string, data: any): Promise<any> | {
6
7
  toPromise(): Promise<any>;
7
8
  };
@@ -17,7 +18,7 @@ export interface HttpProvider {
17
18
  }
18
19
  export declare class HttpProviderBridgeToRestDataProviderHttpProvider implements RestDataProviderHttpProvider {
19
20
  private http;
20
- constructor(http: HttpProvider);
21
+ constructor(http: ExternalHttpProvider);
21
22
  post(url: string, data: any): Promise<any>;
22
23
  delete(url: string): Promise<void>;
23
24
  put(url: string, data: any): Promise<any>;
@@ -37,12 +38,7 @@ export declare class Remult {
37
38
  *
38
39
  */
39
40
  repo<T>(entity: ClassType<T>, dataProvider?: DataProvider): Repository<T>;
40
- /** Returns the current user's info */
41
- get user(): UserInfo;
42
- /** Set's the current user info */
43
- setUser(info: UserInfo | undefined): Promise<void>;
44
- private _user;
45
- private _userChangeEvent;
41
+ user?: UserInfo;
46
42
  /** Checks if a user was authenticated */
47
43
  authenticated(): boolean;
48
44
  /** checks if the user has any of the roles specified in the parameters
@@ -57,30 +53,31 @@ export declare class Remult {
57
53
  * [Allowed](https://remult.dev/docs/allowed.html)
58
54
  */
59
55
  isAllowedForInstance(instance: any, allowed?: AllowedForInstance<any>): boolean;
60
- /** returns a dispatcher object that fires once a user has changed*/
61
- get userChange(): EventDispatcher;
62
- private repCache;
63
56
  /** Creates a new instance of the `remult` object.
64
57
  *
65
58
  * Can receive either an HttpProvider or a DataProvider as a parameter - which will be used to fetch data from.
66
59
  *
67
60
  * If no provider is specified, `fetch` will be used as an http provider
68
61
  */
69
- constructor(provider?: HttpProvider | DataProvider | typeof fetch);
70
- /** The api Base Url to be used in all remult calls. by default it's set to `/api`.
71
- *
72
- * Set this property in case you want to determine a non relative api url
73
- */
74
- static apiBaseUrl: string;
62
+ constructor(http: ExternalHttpProvider | typeof fetch | ApiClient);
63
+ constructor(p: DataProvider);
64
+ constructor();
65
+ call<T extends ((...args: any[]) => Promise<Y>), Y>(backendMethod: T, self?: any): T;
75
66
  /** The current data provider */
76
- _dataSource: DataProvider;
77
- /** sets the current data provider */
78
- setDataProvider(dataProvider: DataProvider): void;
67
+ dataProvider: DataProvider;
79
68
  /** A helper callback that can be used to debug and trace all find operations. Useful in debugging scenarios */
80
69
  static onFind: (metadata: EntityMetadata, options: FindOptions<any>) => void;
81
70
  clearAllCache(): any;
82
71
  /** A helper callback that is called whenever an entity is created. */
83
72
  static entityRefInit?: (ref: EntityRef<any>, row: any) => void;
73
+ readonly context: RemultContext;
74
+ apiClient: ApiClient;
75
+ }
76
+ export interface RemultContext {
77
+ }
78
+ export interface ApiClient {
79
+ httpClient?: ExternalHttpProvider | typeof fetch;
80
+ url?: string;
84
81
  }
85
82
  export declare const allEntities: ClassType<any>[];
86
83
  export interface ControllerOptions {
@@ -93,6 +90,7 @@ export declare class ClassHelper {
93
90
  export declare class MethodHelper {
94
91
  classes: Map<any, ControllerOptions>;
95
92
  }
93
+ export declare function buildRestDataProvider(provider: ExternalHttpProvider | typeof fetch): RestDataProviderHttpProvider | RestDataProviderHttpProviderUsingFetch;
96
94
  export declare function setControllerSettings(target: any, options: ControllerOptions): void;
97
95
  export interface UserInfo {
98
96
  id: string;
@@ -1,4 +1,4 @@
1
- import { Action, actionInfo } from './server-action';
1
+ import { actionInfo, serverActionField } from './server-action';
2
2
  import { RestDataProvider, RestDataProviderHttpProviderUsingFetch } from './data-providers/rest-data-provider';
3
3
  import { RepositoryImplementation } from "./remult3/RepositoryImplementation";
4
4
  export class HttpProviderBridgeToRestDataProviderHttpProvider {
@@ -75,6 +75,8 @@ export async function processHttpException(ex) {
75
75
  message: error,
76
76
  };
77
77
  }
78
+ if (z.modelState)
79
+ error.modelState = z.modelState;
78
80
  let httpStatusCode = z.status;
79
81
  if (httpStatusCode === undefined)
80
82
  httpStatusCode = z.response?.status;
@@ -90,37 +92,31 @@ export function isBackend() {
90
92
  return actionInfo.runningOnServer;
91
93
  }
92
94
  export class Remult {
93
- /** Creates a new instance of the `remult` object.
94
- *
95
- * Can receive either an HttpProvider or a DataProvider as a parameter - which will be used to fetch data from.
96
- *
97
- * If no provider is specified, `fetch` will be used as an http provider
98
- */
99
95
  constructor(provider) {
100
- this._userChangeEvent = new EventSource();
96
+ /* @internal */
101
97
  this.repCache = new Map();
98
+ /** The current data provider */
99
+ this.dataProvider = new RestDataProvider(() => this.apiClient);
100
+ this.context = {};
101
+ this.apiClient = {
102
+ url: '/api'
103
+ };
102
104
  if (provider && provider.getEntityDataProvider) {
103
- this._dataSource = provider;
105
+ this.dataProvider = provider;
104
106
  return;
105
107
  }
106
- let dataProvider;
107
- if (!dataProvider) {
108
- let http = provider;
109
- if (http && http.get && http.put && http.post && http.delete) {
110
- dataProvider = new HttpProviderBridgeToRestDataProviderHttpProvider(http);
111
- }
112
- }
113
- if (!dataProvider) {
114
- if (typeof provider === "function") {
115
- dataProvider = new RestDataProviderHttpProviderUsingFetch(provider);
116
- }
108
+ if (isExternalHttpProvider(provider)) {
109
+ this.apiClient.httpClient = provider;
117
110
  }
118
- if (!dataProvider) {
119
- dataProvider = new RestDataProviderHttpProviderUsingFetch();
111
+ else if (typeof (provider) === "function")
112
+ this.apiClient.httpClient = provider;
113
+ else if (provider) {
114
+ const apiClient = provider;
115
+ if (apiClient.httpClient)
116
+ this.apiClient.httpClient = apiClient.httpClient;
117
+ if (apiClient.url)
118
+ this.apiClient.url = apiClient.url;
120
119
  }
121
- this._dataSource = new RestDataProvider(Remult.apiBaseUrl, dataProvider);
122
- if (!Action.provider)
123
- Action.provider = dataProvider;
124
120
  }
125
121
  /**Return's a `Repository` of the specific entity type
126
122
  * @example
@@ -130,7 +126,7 @@ export class Remult {
130
126
  */
131
127
  repo(entity, dataProvider) {
132
128
  if (dataProvider === undefined)
133
- dataProvider = this._dataSource;
129
+ dataProvider = this.dataProvider;
134
130
  let dpCache = this.repCache.get(dataProvider);
135
131
  if (!dpCache)
136
132
  this.repCache.set(dataProvider, dpCache = new Map());
@@ -140,39 +136,10 @@ export class Remult {
140
136
  }
141
137
  return r;
142
138
  }
143
- /** Returns the current user's info */
144
- get user() {
145
- if (this._user === undefined) {
146
- return {
147
- id: undefined,
148
- name: '',
149
- roles: []
150
- };
151
- }
152
- return this._user;
153
- }
154
- /** Set's the current user info */
155
- async setUser(info) {
156
- this._user = info;
157
- if (this._user === null)
158
- this._user = undefined;
159
- let auth = info;
160
- if (auth) {
161
- if (!this._user.id && auth.sub)
162
- this._user.id = auth.sub;
163
- if (!this._user.roles && auth.permissions) {
164
- this._user.roles = auth.permissions;
165
- }
166
- if (!this._user.name)
167
- this._user.name = auth.username;
168
- }
169
- if (this._user && !this._user.roles)
170
- this._user.roles = [];
171
- await this._userChangeEvent.fire();
172
- }
139
+ /* delete me */
173
140
  /** Checks if a user was authenticated */
174
141
  authenticated() {
175
- return this.user.id !== undefined;
142
+ return this.user?.id !== undefined;
176
143
  }
177
144
  /** checks if the user has any of the roles specified in the parameters
178
145
  * @example
@@ -197,7 +164,7 @@ export class Remult {
197
164
  if (typeof roles === 'boolean')
198
165
  return roles;
199
166
  if (typeof roles === 'string')
200
- if (this.user.roles.indexOf(roles.toString()) >= 0)
167
+ if (this.user?.roles?.indexOf(roles.toString()) >= 0)
201
168
  return true;
202
169
  return false;
203
170
  }
@@ -220,25 +187,22 @@ export class Remult {
220
187
  else
221
188
  return this.isAllowed(allowed);
222
189
  }
223
- /** returns a dispatcher object that fires once a user has changed*/
224
- get userChange() {
225
- return this._userChangeEvent.dispatcher;
226
- }
227
- /** sets the current data provider */
228
- setDataProvider(dataProvider) {
229
- this._dataSource = dataProvider;
190
+ call(backendMethod, self) {
191
+ const z = (backendMethod[serverActionField]);
192
+ if (!z.doWork)
193
+ throw Error("The method received is not a valid backend method");
194
+ //@ts-ignore
195
+ return (...args) => {
196
+ return z.doWork(args, self, this.apiClient.url, buildRestDataProvider(this.apiClient.httpClient));
197
+ };
230
198
  }
231
199
  clearAllCache() {
232
200
  this.repCache.clear();
233
201
  }
234
202
  }
235
- /** The api Base Url to be used in all remult calls. by default it's set to `/api`.
236
- *
237
- * Set this property in case you want to determine a non relative api url
238
- */
239
- Remult.apiBaseUrl = '/api';
240
203
  /** A helper callback that can be used to debug and trace all find operations. Useful in debugging scenarios */
241
204
  Remult.onFind = (metadata, options) => { };
205
+ ;
242
206
  export const allEntities = [];
243
207
  export const classHelpers = new Map();
244
208
  export class ClassHelper {
@@ -251,6 +215,28 @@ export class MethodHelper {
251
215
  this.classes = new Map();
252
216
  }
253
217
  }
218
+ function isExternalHttpProvider(item) {
219
+ let http = item;
220
+ if (http && http.get && http.put && http.post && http.delete)
221
+ return true;
222
+ return false;
223
+ }
224
+ export function buildRestDataProvider(provider) {
225
+ if (!provider)
226
+ return new RestDataProviderHttpProviderUsingFetch();
227
+ let httpDataProvider;
228
+ if (!httpDataProvider) {
229
+ if (isExternalHttpProvider(provider)) {
230
+ httpDataProvider = new HttpProviderBridgeToRestDataProviderHttpProvider(provider);
231
+ }
232
+ }
233
+ if (!httpDataProvider) {
234
+ if (typeof provider === "function") {
235
+ httpDataProvider = new RestDataProviderHttpProviderUsingFetch(provider);
236
+ }
237
+ }
238
+ return httpDataProvider;
239
+ }
254
240
  export function setControllerSettings(target, options) {
255
241
  let r = target;
256
242
  while (true) {
@@ -2,10 +2,10 @@ import { EntityDataProvider, DataProvider, EntityDataProviderFindOptions, RestDa
2
2
  import { UrlBuilder } from '../../urlBuilder';
3
3
  import { Filter } from '../filter/filter-interfaces';
4
4
  import { EntityMetadata } from '../remult3';
5
+ import { ApiClient } from '../context';
5
6
  export declare class RestDataProvider implements DataProvider {
6
- private url;
7
- private http;
8
- constructor(url: string, http: RestDataProviderHttpProvider);
7
+ private apiProvider;
8
+ constructor(apiProvider: () => ApiClient);
9
9
  getEntityDataProvider(entity: EntityMetadata): EntityDataProvider;
10
10
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
11
11
  supportsCustomFilter: boolean;
@@ -14,7 +14,7 @@ export declare class RestEntityDataProvider implements EntityDataProvider {
14
14
  private url;
15
15
  private http;
16
16
  private entity;
17
- constructor(url: string, http: RestDataProviderHttpProvider, entity: EntityMetadata);
17
+ constructor(url: () => string, http: () => RestDataProviderHttpProvider, entity: EntityMetadata);
18
18
  translateFromJson(row: any): {};
19
19
  translateToJson(row: any): {};
20
20
  count(where: Filter): Promise<number>;
@@ -1,14 +1,20 @@
1
1
  import { UrlBuilder } from '../../urlBuilder';
2
2
  import { customUrlToken } from '../filter/filter-interfaces';
3
- import { retry } from '../context';
3
+ import { buildRestDataProvider, retry } from '../context';
4
4
  export class RestDataProvider {
5
- constructor(url, http) {
6
- this.url = url;
7
- this.http = http;
5
+ constructor(apiProvider) {
6
+ this.apiProvider = apiProvider;
8
7
  this.supportsCustomFilter = true;
9
8
  }
10
9
  getEntityDataProvider(entity) {
11
- return new RestEntityDataProvider(this.url + '/' + entity.key, this.http, entity);
10
+ return new RestEntityDataProvider(() => {
11
+ let url = this.apiProvider()?.url;
12
+ if (url === undefined || url === null)
13
+ url = '/api';
14
+ return url + '/' + entity.key;
15
+ }, () => {
16
+ return buildRestDataProvider(this.apiProvider().httpClient);
17
+ }, entity);
12
18
  }
13
19
  async transaction(action) {
14
20
  throw new Error("Method not implemented.");
@@ -35,7 +41,7 @@ export class RestEntityDataProvider {
35
41
  return result;
36
42
  }
37
43
  async count(where) {
38
- let url = new UrlBuilder(this.url);
44
+ let url = new UrlBuilder(this.url());
39
45
  url.add("__action", "count");
40
46
  let filterObject;
41
47
  if (where) {
@@ -44,12 +50,12 @@ export class RestEntityDataProvider {
44
50
  filterObject = undefined;
45
51
  }
46
52
  if (filterObject)
47
- return this.http.post(url.url, filterObject).then(r => +(r.count));
53
+ return this.http().post(url.url, filterObject).then(r => +(r.count));
48
54
  else
49
- return this.http.get(url.url).then(r => +(r.count));
55
+ return this.http().get(url.url).then(r => +(r.count));
50
56
  }
51
57
  find(options) {
52
- let url = new UrlBuilder(this.url);
58
+ let url = new UrlBuilder(this.url());
53
59
  let filterObject;
54
60
  if (options) {
55
61
  if (options.where) {
@@ -78,10 +84,10 @@ export class RestEntityDataProvider {
78
84
  }
79
85
  if (filterObject) {
80
86
  url.add("__action", "get");
81
- return this.http.post(url.url, filterObject).then(x => x.map(y => this.translateFromJson(y)));
87
+ return this.http().post(url.url, filterObject).then(x => x.map(y => this.translateFromJson(y)));
82
88
  }
83
89
  else
84
- return this.http.get(url.url).then(x => x.map(y => this.translateFromJson(y)));
90
+ return this.http().get(url.url).then(x => x.map(y => this.translateFromJson(y)));
85
91
  ;
86
92
  }
87
93
  update(id, data) {
@@ -91,13 +97,13 @@ export class RestEntityDataProvider {
91
97
  if (keys.includes(col.key))
92
98
  result[col.key] = col.valueConverter.toJson(data[col.key]);
93
99
  }
94
- return this.http.put(this.url + '/' + encodeURIComponent(id), result).then(y => this.translateFromJson(y));
100
+ return this.http().put(this.url() + '/' + encodeURIComponent(id), result).then(y => this.translateFromJson(y));
95
101
  }
96
102
  delete(id) {
97
- return this.http.delete(this.url + '/' + encodeURIComponent(id));
103
+ return this.http().delete(this.url() + '/' + encodeURIComponent(id));
98
104
  }
99
105
  insert(data) {
100
- return this.http.post(this.url, this.translateToJson(data)).then(y => this.translateFromJson(y));
106
+ return this.http().post(this.url(), this.translateToJson(data)).then(y => this.translateFromJson(y));
101
107
  }
102
108
  }
103
109
  export class RestDataProviderHttpProviderUsingFetch {
@@ -0,0 +1,2 @@
1
+ import { Remult } from "./context";
2
+ export declare const remult: Remult;