remult 0.26.11-next.1 → 0.26.12-next.0

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 (38) hide show
  1. package/esm/live-query/data-provider-live-query-storage.js +2 -2
  2. package/esm/migrations/generate-migrations.js +2 -2
  3. package/esm/migrations/migrate.js +2 -2
  4. package/esm/remult-sqlite-core.js +3 -3
  5. package/esm/remult-turso.js +59 -0
  6. package/esm/server/JsonEntityFileStorage.js +1 -1
  7. package/esm/server/initDataProvider.js +7 -2
  8. package/esm/server/initDataProviderOrJson.js +6 -0
  9. package/esm/server/remult-api-server.js +44 -32
  10. package/esm/src/context.js +16 -7
  11. package/esm/src/data-providers/json-data-provider.js +8 -4
  12. package/esm/src/live-query/LiveQueryClient.js +2 -9
  13. package/esm/src/live-query/SubscriptionChannel.js +0 -2
  14. package/esm/src/remult-static.js +1 -0
  15. package/esm/src/remult3/remult3.js +15 -8
  16. package/live-query/data-provider-live-query-storage.js +2 -2
  17. package/migrations/generate-migrations.js +2 -2
  18. package/migrations/migrate.js +2 -2
  19. package/package.json +6 -1
  20. package/remult-sqlite-core.js +15 -10
  21. package/remult-sqlite3.d.ts +1 -1
  22. package/remult-turso.d.ts +8 -0
  23. package/remult-turso.js +100 -0
  24. package/server/JsonEntityFileStorage.js +1 -1
  25. package/server/initDataProvider.d.ts +1 -1
  26. package/server/initDataProvider.js +11 -3
  27. package/server/initDataProviderOrJson.d.ts +2 -0
  28. package/server/initDataProviderOrJson.js +17 -0
  29. package/server/remult-api-server.js +36 -23
  30. package/src/context.d.ts +11 -3
  31. package/src/context.js +33 -8
  32. package/src/data-providers/json-data-provider.d.ts +2 -1
  33. package/src/data-providers/json-data-provider.js +14 -9
  34. package/src/live-query/LiveQueryClient.js +2 -10
  35. package/src/live-query/SubscriptionChannel.js +1 -4
  36. package/src/remult-static.d.ts +2 -0
  37. package/src/remult-static.js +1 -0
  38. package/src/remult3/remult3.js +15 -8
@@ -1,15 +1,15 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
- import { initDataProvider } from '../server/initDataProvider.js';
3
2
  import { Remult } from '../src/context.js';
4
3
  import { EntityBase } from '../src/remult3/RepositoryImplementation.js';
5
4
  import { Fields } from '../src/remult3/Fields.js';
6
5
  import { Entity } from '../src/remult3/entity.js';
7
6
  import { remultStatic } from '../src/remult-static.js';
7
+ import { initDataProviderOrJson } from '../server/initDataProviderOrJson';
8
8
  export class DataProviderLiveQueryStorage {
9
9
  repo;
10
10
  dataProvider;
11
11
  constructor(dataProvider) {
12
- this.dataProvider = initDataProvider(dataProvider);
12
+ this.dataProvider = initDataProviderOrJson(dataProvider);
13
13
  this.repo = this.dataProvider.then((dp) => new Remult(dp).repo(LiveQueryStorageEntity));
14
14
  }
15
15
  async ensureSchema() {
@@ -4,7 +4,7 @@ import { compareMigrationSnapshot, emptySnapshot, } from './compare-migration-sn
4
4
  import { updateMigrationsFile } from './update-migrations-ts-file.js';
5
5
  import { DefaultMigrationBuilder, } from './migration-types.js';
6
6
  import { isOfType } from '../src/isOfType.js';
7
- import { initDataProvider } from '../server/initDataProvider.js';
7
+ import { initDataProviderOrJson } from '../server/initDataProviderOrJson';
8
8
  /**
9
9
  * Generates migration scripts based on changes in entities.
10
10
  *
@@ -21,7 +21,7 @@ export async function generateMigrations(options) {
21
21
  const migrationDir = options.migrationsFolder || path.join(process.cwd(), 'src/migrations');
22
22
  const snapshotFileName = options.snapshotFile || path.join(migrationDir, 'migrations-snapshot.json');
23
23
  const migrationsTSFilename = options.migrationsTSFile || path.join(migrationDir, 'migrations.ts');
24
- const dataProvider = await initDataProvider(options.dataProvider);
24
+ const dataProvider = await initDataProviderOrJson(options.dataProvider);
25
25
  for (const p of [snapshotFileName, migrationsTSFilename]) {
26
26
  if (!fs.existsSync(path.dirname(p))) {
27
27
  fs.mkdirSync(path.dirname(p), { recursive: true });
@@ -1,6 +1,6 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import { Entity, IdEntity, Fields, remult, Remult, } from '../index.js';
3
- import { initDataProvider } from '../server/initDataProvider.js';
3
+ import { initDataProviderOrJson } from '../server/initDataProviderOrJson';
4
4
  import { doTransaction } from '../src/context.js';
5
5
  import { cast, isOfType } from '../src/isOfType.js';
6
6
  /**
@@ -17,7 +17,7 @@ import { cast, isOfType } from '../src/isOfType.js';
17
17
  */
18
18
  export async function migrate(options) {
19
19
  let migrationTableName = options.migrationsTable || '__remult_migrations_version';
20
- const dataProvider = await initDataProvider(options.dataProvider);
20
+ const dataProvider = await initDataProviderOrJson(options.dataProvider);
21
21
  const prev = remult.dataProvider;
22
22
  remult.dataProvider = dataProvider;
23
23
  try {
@@ -29,13 +29,13 @@ export class SqliteCoreDataProvider {
29
29
  };
30
30
  }
31
31
  async transaction(action) {
32
- this.createCommand().execute('Begin Transaction');
32
+ await this.createCommand().execute('Begin Transaction');
33
33
  try {
34
34
  await action(this);
35
- this.createCommand().execute('Commit');
35
+ await this.createCommand().execute('Commit');
36
36
  }
37
37
  catch (err) {
38
- this.createCommand().execute('Rollback');
38
+ await this.createCommand().execute('Rollback');
39
39
  throw err;
40
40
  }
41
41
  }
@@ -0,0 +1,59 @@
1
+ import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
2
+ import { cast } from './src/isOfType.js';
3
+ export class TursoDataProvider extends SqliteCoreDataProvider {
4
+ client;
5
+ constructor(client) {
6
+ super(() => new TursoCommand(client), async () => {
7
+ await cast(this.client, 'close').close();
8
+ }, false);
9
+ this.client = client;
10
+ }
11
+ async transaction(action) {
12
+ const trans = await cast(this.client, 'transaction').transaction();
13
+ try {
14
+ await action(new TursoDataProvider(trans));
15
+ await trans.commit();
16
+ }
17
+ catch (err) {
18
+ await trans.rollback();
19
+ throw err;
20
+ }
21
+ }
22
+ }
23
+ class TursoCommand {
24
+ db;
25
+ values = {};
26
+ i = 1;
27
+ constructor(db) {
28
+ this.db = db;
29
+ }
30
+ async execute(sql) {
31
+ return new TursoSqlResult(await this.db.execute({
32
+ sql,
33
+ args: this.values,
34
+ }));
35
+ }
36
+ addParameterAndReturnSqlToken(val) {
37
+ return this.param(val);
38
+ }
39
+ param(val) {
40
+ if (val instanceof Date)
41
+ val = val.valueOf();
42
+ if (typeof val === 'boolean')
43
+ val = val ? 1 : 0;
44
+ const key = ':' + this.i++;
45
+ this.values[key.substring(1)] = val;
46
+ return key;
47
+ }
48
+ }
49
+ class TursoSqlResult {
50
+ result;
51
+ constructor(result) {
52
+ this.result = result;
53
+ this.rows = result.rows;
54
+ }
55
+ rows;
56
+ getColumnKeyInResultForIndexInSelect(index) {
57
+ return this.result.columns[index];
58
+ }
59
+ }
@@ -22,6 +22,6 @@ export class JsonEntityFileStorage {
22
22
  }
23
23
  export class JsonFileDataProvider extends JsonDataProvider {
24
24
  constructor(folderPath) {
25
- super(new JsonEntityFileStorage(folderPath));
25
+ super(new JsonEntityFileStorage(folderPath), true);
26
26
  }
27
27
  }
@@ -1,4 +1,5 @@
1
- export function initDataProvider(optionsDataProvider) {
1
+ import { remultStatic } from '../src/remult-static';
2
+ export function initDataProvider(optionsDataProvider, useStaticDefault, defaultDataProvider) {
2
3
  let dataProvider;
3
4
  if (typeof optionsDataProvider === 'function') {
4
5
  dataProvider = optionsDataProvider();
@@ -8,7 +9,11 @@ export function initDataProvider(optionsDataProvider) {
8
9
  dataProvider = dataProvider.then(async (dp) => {
9
10
  if (dp)
10
11
  return dp;
11
- return new (await import('./JsonEntityFileStorage.js')).JsonFileDataProvider('./db');
12
+ if (useStaticDefault)
13
+ dp = await remultStatic.defaultDataProvider();
14
+ if (dp)
15
+ return dp;
16
+ return defaultDataProvider?.();
12
17
  });
13
18
  return dataProvider;
14
19
  }
@@ -0,0 +1,6 @@
1
+ import { initDataProvider } from './initDataProvider';
2
+ export function initDataProviderOrJson(dataProvider) {
3
+ return initDataProvider(dataProvider, false, async () => {
4
+ return new (await import('./JsonEntityFileStorage.js')).JsonFileDataProvider('./db');
5
+ });
6
+ }
@@ -10,10 +10,10 @@ import { Entity } from '../src/remult3/entity.js';
10
10
  import { getEntityKey } from '../src/remult3/getEntityRef.js';
11
11
  import { Action, classBackendMethodsArray } from '../src/server-action.js';
12
12
  import { serverActionField } from '../src/server-action-info.js';
13
- import { initDataProvider } from './initDataProvider.js';
14
13
  import { remultStatic } from '../src/remult-static.js';
15
14
  import remultAdminHtml from './remult-admin.js';
16
15
  import { isOfType } from '../src/isOfType.js';
16
+ import { initDataProviderOrJson } from './initDataProviderOrJson';
17
17
  export function createRemultServerCore(options, serverCoreOptions) {
18
18
  if (!options) {
19
19
  options = {};
@@ -30,7 +30,8 @@ export function createRemultServerCore(options, serverCoreOptions) {
30
30
  if (!options.queueStorage) {
31
31
  options.queueStorage = new InMemoryQueueStorage();
32
32
  }
33
- let dataProvider = initDataProvider(options.dataProvider);
33
+ let dataProvider = initDataProviderOrJson(options.dataProvider);
34
+ remultStatic.defaultDataProvider = () => dataProvider;
34
35
  if (options.ensureSchema === undefined)
35
36
  options.ensureSchema = true;
36
37
  RemultAsyncLocalStorage.enable();
@@ -277,6 +278,8 @@ export class RemultServerImplementation {
277
278
  x.subscriptionServer = this.subscriptionServer;
278
279
  x.liveQueryStorage = this.liveQueryStorage;
279
280
  return await what(x);
281
+ }, {
282
+ dataProvider,
280
283
  });
281
284
  }
282
285
  process(what) {
@@ -293,37 +296,46 @@ export class RemultServerImplementation {
293
296
  }
294
297
  let myReq = new ExpressRequestBridgeToDataApiRequest(genReq);
295
298
  let myRes = new ExpressResponseBridgeToDataApiResponse(origRes, req, this.options.error);
296
- try {
297
- await this.runWithRemult(async (remult) => {
298
- if (req) {
299
- let user;
300
- if (this.options.getUser)
301
- user = await this.options.getUser(req);
302
- else {
303
- user = req['user'];
304
- if (!user)
305
- user = req['auth'];
306
- }
307
- if (user)
308
- remult.user = user;
309
- if (this.options.initRequest) {
310
- await this.options.initRequest(req, {
311
- remult,
312
- get liveQueryStorage() {
313
- return remult.liveQueryStorage;
314
- },
315
- set liveQueryStorage(value) {
316
- remult.liveQueryStorage = value;
317
- },
318
- });
299
+ if (remultStatic.asyncContext.isInInitRequest())
300
+ return await what(remultStatic.asyncContext.getStore().remult, myReq, myRes, genReq, origRes, req);
301
+ else
302
+ try {
303
+ await this.runWithRemult(async (remult) => {
304
+ if (req) {
305
+ remultStatic.asyncContext.setInInitRequest(true);
306
+ try {
307
+ let user;
308
+ if (this.options.getUser)
309
+ user = await this.options.getUser(req);
310
+ else {
311
+ user = req['user'];
312
+ if (!user)
313
+ user = req['auth'];
314
+ }
315
+ if (user)
316
+ remult.user = user;
317
+ if (this.options.initRequest) {
318
+ await this.options.initRequest(req, {
319
+ remult,
320
+ get liveQueryStorage() {
321
+ return remult.liveQueryStorage;
322
+ },
323
+ set liveQueryStorage(value) {
324
+ remult.liveQueryStorage = value;
325
+ },
326
+ });
327
+ }
328
+ }
329
+ finally {
330
+ remultStatic.asyncContext.setInInitRequest(false);
331
+ }
319
332
  }
320
- }
321
- await what(remult, myReq, myRes, genReq, origRes, req);
322
- });
323
- }
324
- catch (err) {
325
- myRes.error(err, undefined);
326
- }
333
+ await what(remult, myReq, myRes, genReq, origRes, req);
334
+ });
335
+ }
336
+ catch (err) {
337
+ myRes.error(err, undefined);
338
+ }
327
339
  };
328
340
  }
329
341
  async getRemult(req) {
@@ -7,13 +7,14 @@ import { serverActionField } from './server-action-info.js';
7
7
  import { buildRestDataProvider, isExternalHttpProvider, } from './buildRestDataProvider.js';
8
8
  import { verifyFieldRelationInfo } from './remult3/relationInfoMember.js';
9
9
  import { remultStatic, resetFactory } from './remult-static.js';
10
+ import { initDataProvider } from '../server/initDataProvider';
10
11
  export class RemultAsyncLocalStorage {
11
12
  remultObjectStorage;
12
13
  static enable() {
13
14
  remultStatic.remultFactory = () => {
14
- const r = remultStatic.asyncContext.getRemult();
15
+ const r = remultStatic.asyncContext.getStore();
15
16
  if (r)
16
- return r;
17
+ return r.remult;
17
18
  else
18
19
  throw new Error('remult object was requested outside of a valid context, try running it within initApi or a remult request cycle');
19
20
  };
@@ -26,12 +27,21 @@ export class RemultAsyncLocalStorage {
26
27
  }
27
28
  async run(remult, callback) {
28
29
  if (this.remultObjectStorage) {
29
- return this.remultObjectStorage.run(remult, () => callback(remult));
30
+ return this.remultObjectStorage.run({ remult }, () => callback(remult));
30
31
  }
31
32
  else
32
33
  return callback(remult);
33
34
  }
34
- getRemult() {
35
+ isInInitRequest() {
36
+ return this.remultObjectStorage?.getStore()?.inInitRequest;
37
+ }
38
+ setInInitRequest(val) {
39
+ const store = this.remultObjectStorage?.getStore();
40
+ if (!store)
41
+ return;
42
+ store.inInitRequest = val;
43
+ }
44
+ getStore() {
35
45
  if (!this.remultObjectStorage) {
36
46
  throw new Error("can't use static remult in this environment, `async_hooks` were not initialized");
37
47
  }
@@ -282,9 +292,8 @@ class transactionLiveQueryPublisher {
282
292
  }
283
293
  }
284
294
  }
285
- export function withRemult(callback, options) {
295
+ export async function withRemult(callback, options) {
286
296
  const remult = new Remult();
287
- if (options?.dataProvider)
288
- remult.dataProvider = options.dataProvider;
297
+ remult.dataProvider = await initDataProvider(options?.dataProvider, true, async () => remult.dataProvider);
289
298
  return remultStatic.asyncContext.run(remult, (r) => callback(r));
290
299
  }
@@ -1,11 +1,13 @@
1
1
  import { ArrayEntityDataProvider } from './array-entity-data-provider.js';
2
2
  export class JsonDataProvider {
3
3
  storage;
4
- constructor(storage) {
4
+ formatted;
5
+ constructor(storage, formatted = false) {
5
6
  this.storage = storage;
7
+ this.formatted = formatted;
6
8
  }
7
9
  getEntityDataProvider(entity) {
8
- return new JsonEntityDataProvider(entity, this.storage);
10
+ return new JsonEntityDataProvider(entity, this.storage, this.formatted);
9
11
  }
10
12
  async transaction(action) {
11
13
  await action(this);
@@ -14,9 +16,11 @@ export class JsonDataProvider {
14
16
  class JsonEntityDataProvider {
15
17
  entity;
16
18
  helper;
17
- constructor(entity, helper) {
19
+ formatted;
20
+ constructor(entity, helper, formatted) {
18
21
  this.entity = entity;
19
22
  this.helper = helper;
23
+ this.formatted = formatted;
20
24
  }
21
25
  async loadEntityData(what) {
22
26
  let data = [];
@@ -25,7 +29,7 @@ class JsonEntityDataProvider {
25
29
  if (s)
26
30
  data = JSON.parse(s);
27
31
  let dp = new ArrayEntityDataProvider(this.entity, () => data);
28
- return what(dp, async () => await this.helper.setItem(dbName, JSON.stringify(data, undefined, 2)));
32
+ return what(dp, async () => await this.helper.setItem(dbName, JSON.stringify(data, undefined, this.formatted ? 2 : undefined)));
29
33
  }
30
34
  p = Promise.resolve();
31
35
  find(options) {
@@ -67,7 +67,7 @@ export class LiveQueryClient {
67
67
  onUnsubscribe = () => { };
68
68
  };
69
69
  }
70
- _actuallyClose() {
70
+ closeIfNoListeners() {
71
71
  if (this.client)
72
72
  if (this.queries.size === 0 && this.channels.size === 0) {
73
73
  this.runPromise(this.client.then((x) => x.close()));
@@ -76,12 +76,6 @@ export class LiveQueryClient {
76
76
  this.interval = undefined;
77
77
  }
78
78
  }
79
- keepAliveMs = 1000;
80
- closeIfNoListeners() {
81
- setTimeout(() => {
82
- this._actuallyClose();
83
- }, this.keepAliveMs);
84
- }
85
79
  subscribe(repo, options, listener) {
86
80
  let alive = true;
87
81
  let onUnsubscribe = () => {
@@ -168,8 +162,7 @@ export class LiveQueryClient {
168
162
  this.interval = setInterval(async () => {
169
163
  const ids = [];
170
164
  for (const q of this.queries.values()) {
171
- if (q.gotAnyResult)
172
- ids.push(q.queryChannel);
165
+ ids.push(q.queryChannel);
173
166
  }
174
167
  if (ids.length > 0) {
175
168
  let p = this.apiProvider();
@@ -10,12 +10,10 @@ export class LiveQuerySubscriber {
10
10
  sendDefaultState(onResult) {
11
11
  onResult(this.createReducerType(() => [...this.defaultQueryState], this.allItemsMessage(this.defaultQueryState)));
12
12
  }
13
- gotAnyResult = false;
14
13
  queryChannel;
15
14
  subscribeCode;
16
15
  unsubscribe = () => { };
17
16
  async setAllItems(result) {
18
- this.gotAnyResult = true;
19
17
  const items = await getRepositoryInternals(this.repo)._fromJsonArray(result, this.query.options);
20
18
  this.forListeners((listener) => {
21
19
  listener(() => {
@@ -19,6 +19,7 @@ let x = {
19
19
  }),
20
20
  },
21
21
  captionTransformer: undefined,
22
+ defaultDataProvider: () => undefined,
22
23
  };
23
24
  if ((typeof process !== 'undefined' &&
24
25
  process.env['IGNORE_GLOBAL_REMULT_IN_TESTS']) ||
@@ -1,15 +1,17 @@
1
1
  export const flags = {
2
2
  error500RetryCount: 4,
3
3
  };
4
- //y2 - soft-delete-discussion https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
5
4
  //y1 - live query with count #436
6
- //y1 - live query errort that appears in tests but I can't understand why - `open connection error `
5
+ //y1 - https://github.com/remult/remult/discussions/438
6
+ //p1 - discuss next auth withRemult paradox
7
+ //p1 - maybe the default withRemult should by default use the data provider set by the remultExpress
8
+ //p1 - withRemult to support the full range of data provider.
7
9
  //y1 TODO - In the esm version of our tutorial - the imports are automatically .ts and not .js in react and not in vue
8
10
  //y1 TODO - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
9
11
  //y1 TODO - readonly key: keyof MembersOnly<entityType> & string
10
12
  //y1 - talk about insert / update / delete with relations
11
13
  /*
12
- repo(Order).insert({},{
14
+ repo(Order).insert({},{
13
15
  relations:{
14
16
  orderItems:[{},{},{}]
15
17
  }
@@ -17,13 +19,16 @@ export const flags = {
17
19
  */
18
20
  //y1 - repo batch - for multiple operations:
19
21
  /*
20
- const result = await repo.batch(x=>({
21
- data:x.find(),
22
- count:x.count()
23
- }))
22
+ const result = await repo.batch(x=>({
23
+ data:x.find(),
24
+ count:x.count()
25
+ }))
24
26
  */
27
+ //p1 - consider in json storage, to store the json without spaces
25
28
  //p1 - consider upsert (where,set)
26
- //p1 - wait a second to close stream
29
+ //y1 - wait a second to close stream -see pr
30
+ //p1 - Consider enforcing serial operations on JSON database to prevent data loss
31
+ //y2 - soft-delete-discussion https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
27
32
  //p1 - prepare the createEntity discussion
28
33
  //p1 - return error on connection error
29
34
  //p1 - article on displayValue including it's definition for entities that is used in relations
@@ -81,6 +86,8 @@ export const flags = {
81
86
  //p1 - when a tasks table exists in a different schema - we get many errors
82
87
  //p1 - live query with include
83
88
  //p1 - adjust angular tutorial starter kit for latest angular (as is in tutorial)
89
+ //y2 - Fix problem with promise all in sql expression recurssion - when using PromiseAll in row relation loading, some sql expressions appear is recursion call even if they are not
90
+ //p2 - when subscribe is forbidden - the query still runs after the renew process
84
91
  //p2 - 'update tasks set where id = $1
85
92
  //p2 - type metadata.key - to keyof entity - based on cwis input
86
93
  //y2 - remove __dirname from tutorials
@@ -2,15 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LiveQueryStorageEntity = exports.DataProviderLiveQueryStorage = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var initDataProvider_js_1 = require("../server/initDataProvider.js");
6
5
  var context_js_1 = require("../src/context.js");
7
6
  var RepositoryImplementation_js_1 = require("../src/remult3/RepositoryImplementation.js");
8
7
  var Fields_js_1 = require("../src/remult3/Fields.js");
9
8
  var entity_js_1 = require("../src/remult3/entity.js");
10
9
  var remult_static_js_1 = require("../src/remult-static.js");
10
+ var initDataProviderOrJson_1 = require("../server/initDataProviderOrJson");
11
11
  var DataProviderLiveQueryStorage = /** @class */ (function () {
12
12
  function DataProviderLiveQueryStorage(dataProvider) {
13
- this.dataProvider = (0, initDataProvider_js_1.initDataProvider)(dataProvider);
13
+ this.dataProvider = (0, initDataProviderOrJson_1.initDataProviderOrJson)(dataProvider);
14
14
  this.repo = this.dataProvider.then(function (dp) {
15
15
  return new context_js_1.Remult(dp).repo(LiveQueryStorageEntity);
16
16
  });
@@ -8,7 +8,7 @@ var compare_migration_snapshots_js_1 = require("./compare-migration-snapshots.js
8
8
  var update_migrations_ts_file_js_1 = require("./update-migrations-ts-file.js");
9
9
  var migration_types_js_1 = require("./migration-types.js");
10
10
  var isOfType_js_1 = require("../src/isOfType.js");
11
- var initDataProvider_js_1 = require("../server/initDataProvider.js");
11
+ var initDataProviderOrJson_1 = require("../server/initDataProviderOrJson");
12
12
  /**
13
13
  * Generates migration scripts based on changes in entities.
14
14
  *
@@ -31,7 +31,7 @@ function generateMigrations(options) {
31
31
  migrationDir = options.migrationsFolder || path_1.default.join(process.cwd(), 'src/migrations');
32
32
  snapshotFileName = options.snapshotFile || path_1.default.join(migrationDir, 'migrations-snapshot.json');
33
33
  migrationsTSFilename = options.migrationsTSFile || path_1.default.join(migrationDir, 'migrations.ts');
34
- return [4 /*yield*/, (0, initDataProvider_js_1.initDataProvider)(options.dataProvider)];
34
+ return [4 /*yield*/, (0, initDataProviderOrJson_1.initDataProviderOrJson)(options.dataProvider)];
35
35
  case 1:
36
36
  dataProvider = _d.sent();
37
37
  try {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.migrate = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var index_js_1 = require("../index.js");
6
- var initDataProvider_js_1 = require("../server/initDataProvider.js");
6
+ var initDataProviderOrJson_1 = require("../server/initDataProviderOrJson");
7
7
  var context_js_1 = require("../src/context.js");
8
8
  var isOfType_js_1 = require("../src/isOfType.js");
9
9
  /**
@@ -26,7 +26,7 @@ function migrate(options) {
26
26
  switch (_a.label) {
27
27
  case 0:
28
28
  migrationTableName = options.migrationsTable || '__remult_migrations_version';
29
- return [4 /*yield*/, (0, initDataProvider_js_1.initDataProvider)(options.dataProvider)];
29
+ return [4 /*yield*/, (0, initDataProviderOrJson_1.initDataProviderOrJson)(options.dataProvider)];
30
30
  case 1:
31
31
  dataProvider = _a.sent();
32
32
  prev = index_js_1.remult.dataProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.26.11-next.1",
3
+ "version": "0.26.12-next.0",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -116,6 +116,11 @@
116
116
  "import": "./esm/remult-sqlite3.js",
117
117
  "types": "./remult-sqlite3.d.ts"
118
118
  },
119
+ "./remult-turso": {
120
+ "require": "./remult-turso.js",
121
+ "import": "./esm/remult-turso.js",
122
+ "types": "./remult-turso.d.ts"
123
+ },
119
124
  "./remult-bun-sqlite": {
120
125
  "require": "./remult-bun-sqlite.js",
121
126
  "import": "./esm/remult-bun-sqlite.js",
@@ -52,21 +52,26 @@ var SqliteCoreDataProvider = /** @class */ (function () {
52
52
  var err_1;
53
53
  return tslib_1.__generator(this, function (_a) {
54
54
  switch (_a.label) {
55
- case 0:
56
- this.createCommand().execute('Begin Transaction');
57
- _a.label = 1;
55
+ case 0: return [4 /*yield*/, this.createCommand().execute('Begin Transaction')];
58
56
  case 1:
59
- _a.trys.push([1, 3, , 4]);
60
- return [4 /*yield*/, action(this)];
61
- case 2:
62
57
  _a.sent();
63
- this.createCommand().execute('Commit');
64
- return [3 /*break*/, 4];
58
+ _a.label = 2;
59
+ case 2:
60
+ _a.trys.push([2, 5, , 7]);
61
+ return [4 /*yield*/, action(this)];
65
62
  case 3:
63
+ _a.sent();
64
+ return [4 /*yield*/, this.createCommand().execute('Commit')];
65
+ case 4:
66
+ _a.sent();
67
+ return [3 /*break*/, 7];
68
+ case 5:
66
69
  err_1 = _a.sent();
67
- this.createCommand().execute('Rollback');
70
+ return [4 /*yield*/, this.createCommand().execute('Rollback')];
71
+ case 6:
72
+ _a.sent();
68
73
  throw err_1;
69
- case 4: return [2 /*return*/];
74
+ case 7: return [2 /*return*/];
70
75
  }
71
76
  });
72
77
  });
@@ -1,5 +1,5 @@
1
1
  import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
2
- import { Database } from 'sqlite3';
2
+ import type { Database } from 'sqlite3';
3
3
  export declare class Sqlite3DataProvider extends SqliteCoreDataProvider {
4
4
  constructor(db: Database);
5
5
  }
@@ -0,0 +1,8 @@
1
+ import { SqlImplementation } from './index.js';
2
+ import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
3
+ import type { Client } from '@libsql/client';
4
+ export declare class TursoDataProvider extends SqliteCoreDataProvider {
5
+ private client;
6
+ constructor(client: Pick<Client, 'execute'>);
7
+ transaction(action: (sql: SqlImplementation) => Promise<void>): Promise<void>;
8
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TursoDataProvider = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var remult_sqlite_core_js_1 = require("./remult-sqlite-core.js");
6
+ var isOfType_js_1 = require("./src/isOfType.js");
7
+ var TursoDataProvider = /** @class */ (function (_super) {
8
+ tslib_1.__extends(TursoDataProvider, _super);
9
+ function TursoDataProvider(client) {
10
+ var _this = _super.call(this, function () { return new TursoCommand(client); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
11
+ return tslib_1.__generator(this, function (_a) {
12
+ switch (_a.label) {
13
+ case 0: return [4 /*yield*/, (0, isOfType_js_1.cast)(this.client, 'close').close()];
14
+ case 1:
15
+ _a.sent();
16
+ return [2 /*return*/];
17
+ }
18
+ });
19
+ }); }, false) || this;
20
+ _this.client = client;
21
+ return _this;
22
+ }
23
+ TursoDataProvider.prototype.transaction = function (action) {
24
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
25
+ var trans, err_1;
26
+ return tslib_1.__generator(this, function (_a) {
27
+ switch (_a.label) {
28
+ case 0: return [4 /*yield*/, (0, isOfType_js_1.cast)(this.client, 'transaction').transaction()];
29
+ case 1:
30
+ trans = _a.sent();
31
+ _a.label = 2;
32
+ case 2:
33
+ _a.trys.push([2, 5, , 7]);
34
+ return [4 /*yield*/, action(new TursoDataProvider(trans))];
35
+ case 3:
36
+ _a.sent();
37
+ return [4 /*yield*/, trans.commit()];
38
+ case 4:
39
+ _a.sent();
40
+ return [3 /*break*/, 7];
41
+ case 5:
42
+ err_1 = _a.sent();
43
+ return [4 /*yield*/, trans.rollback()];
44
+ case 6:
45
+ _a.sent();
46
+ throw err_1;
47
+ case 7: return [2 /*return*/];
48
+ }
49
+ });
50
+ });
51
+ };
52
+ return TursoDataProvider;
53
+ }(remult_sqlite_core_js_1.SqliteCoreDataProvider));
54
+ exports.TursoDataProvider = TursoDataProvider;
55
+ var TursoCommand = /** @class */ (function () {
56
+ function TursoCommand(db) {
57
+ this.db = db;
58
+ this.values = {};
59
+ this.i = 1;
60
+ }
61
+ TursoCommand.prototype.execute = function (sql) {
62
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
63
+ var _a;
64
+ return tslib_1.__generator(this, function (_b) {
65
+ switch (_b.label) {
66
+ case 0:
67
+ _a = TursoSqlResult.bind;
68
+ return [4 /*yield*/, this.db.execute({
69
+ sql: sql,
70
+ args: this.values,
71
+ })];
72
+ case 1: return [2 /*return*/, new (_a.apply(TursoSqlResult, [void 0, _b.sent()]))()];
73
+ }
74
+ });
75
+ });
76
+ };
77
+ TursoCommand.prototype.addParameterAndReturnSqlToken = function (val) {
78
+ return this.param(val);
79
+ };
80
+ TursoCommand.prototype.param = function (val) {
81
+ if (val instanceof Date)
82
+ val = val.valueOf();
83
+ if (typeof val === 'boolean')
84
+ val = val ? 1 : 0;
85
+ var key = ':' + this.i++;
86
+ this.values[key.substring(1)] = val;
87
+ return key;
88
+ };
89
+ return TursoCommand;
90
+ }());
91
+ var TursoSqlResult = /** @class */ (function () {
92
+ function TursoSqlResult(result) {
93
+ this.result = result;
94
+ this.rows = result.rows;
95
+ }
96
+ TursoSqlResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
97
+ return this.result.columns[index];
98
+ };
99
+ return TursoSqlResult;
100
+ }());
@@ -28,7 +28,7 @@ exports.JsonEntityFileStorage = JsonEntityFileStorage;
28
28
  var JsonFileDataProvider = /** @class */ (function (_super) {
29
29
  tslib_1.__extends(JsonFileDataProvider, _super);
30
30
  function JsonFileDataProvider(folderPath) {
31
- return _super.call(this, new JsonEntityFileStorage(folderPath)) || this;
31
+ return _super.call(this, new JsonEntityFileStorage(folderPath), true) || this;
32
32
  }
33
33
  return JsonFileDataProvider;
34
34
  }(index_js_1.JsonDataProvider));
@@ -1,2 +1,2 @@
1
1
  import type { DataProvider } from '../src/data-interfaces.js';
2
- export declare function initDataProvider(optionsDataProvider?: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>)): Promise<DataProvider>;
2
+ export declare function initDataProvider(optionsDataProvider: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>) | undefined, useStaticDefault: boolean, defaultDataProvider: () => Promise<DataProvider>): Promise<DataProvider>;
@@ -2,7 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initDataProvider = void 0;
4
4
  var tslib_1 = require("tslib");
5
- function initDataProvider(optionsDataProvider) {
5
+ var remult_static_1 = require("../src/remult-static");
6
+ function initDataProvider(optionsDataProvider, useStaticDefault, defaultDataProvider) {
6
7
  var _this = this;
7
8
  var dataProvider;
8
9
  if (typeof optionsDataProvider === 'function') {
@@ -16,8 +17,15 @@ function initDataProvider(optionsDataProvider) {
16
17
  case 0:
17
18
  if (dp)
18
19
  return [2 /*return*/, dp];
19
- return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('./JsonEntityFileStorage.js')); })];
20
- case 1: return [2 /*return*/, new (_a.sent()).JsonFileDataProvider('./db')];
20
+ if (!useStaticDefault) return [3 /*break*/, 2];
21
+ return [4 /*yield*/, remult_static_1.remultStatic.defaultDataProvider()];
22
+ case 1:
23
+ dp = _a.sent();
24
+ _a.label = 2;
25
+ case 2:
26
+ if (dp)
27
+ return [2 /*return*/, dp];
28
+ return [2 /*return*/, defaultDataProvider === null || defaultDataProvider === void 0 ? void 0 : defaultDataProvider()];
21
29
  }
22
30
  });
23
31
  }); });
@@ -0,0 +1,2 @@
1
+ import { DataProvider } from '../src/data-interfaces';
2
+ export declare function initDataProviderOrJson(dataProvider: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>) | undefined): Promise<DataProvider>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initDataProviderOrJson = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var initDataProvider_1 = require("./initDataProvider");
6
+ function initDataProviderOrJson(dataProvider) {
7
+ var _this = this;
8
+ return (0, initDataProvider_1.initDataProvider)(dataProvider, false, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
9
+ return tslib_1.__generator(this, function (_a) {
10
+ switch (_a.label) {
11
+ case 0: return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('./JsonEntityFileStorage.js')); })];
12
+ case 1: return [2 /*return*/, new (_a.sent()).JsonFileDataProvider('./db')];
13
+ }
14
+ });
15
+ }); });
16
+ }
17
+ exports.initDataProviderOrJson = initDataProviderOrJson;
@@ -13,10 +13,10 @@ var entity_js_1 = require("../src/remult3/entity.js");
13
13
  var getEntityRef_js_1 = require("../src/remult3/getEntityRef.js");
14
14
  var server_action_js_1 = require("../src/server-action.js");
15
15
  var server_action_info_js_1 = require("../src/server-action-info.js");
16
- var initDataProvider_js_1 = require("./initDataProvider.js");
17
16
  var remult_static_js_1 = require("../src/remult-static.js");
18
17
  var remult_admin_js_1 = tslib_1.__importDefault(require("./remult-admin.js"));
19
18
  var isOfType_js_1 = require("../src/isOfType.js");
19
+ var initDataProviderOrJson_1 = require("./initDataProviderOrJson");
20
20
  function createRemultServerCore(options, serverCoreOptions) {
21
21
  if (!options) {
22
22
  options = {};
@@ -33,7 +33,8 @@ function createRemultServerCore(options, serverCoreOptions) {
33
33
  if (!options.queueStorage) {
34
34
  options.queueStorage = new InMemoryQueueStorage();
35
35
  }
36
- var dataProvider = (0, initDataProvider_js_1.initDataProvider)(options.dataProvider);
36
+ var dataProvider = (0, initDataProviderOrJson_1.initDataProviderOrJson)(options.dataProvider);
37
+ remult_static_js_1.remultStatic.defaultDataProvider = function () { return dataProvider; };
37
38
  if (options.ensureSchema === undefined)
38
39
  options.ensureSchema = true;
39
40
  context_js_1.RemultAsyncLocalStorage.enable();
@@ -524,7 +525,9 @@ var RemultServerImplementation = /** @class */ (function () {
524
525
  case 1: return [2 /*return*/, _a.sent()];
525
526
  }
526
527
  });
527
- }); })];
528
+ }); }, {
529
+ dataProvider: dataProvider,
530
+ })];
528
531
  case 3: return [2 /*return*/, _a.sent()];
529
532
  }
530
533
  });
@@ -550,30 +553,36 @@ var RemultServerImplementation = /** @class */ (function () {
550
553
  }
551
554
  myReq = new ExpressRequestBridgeToDataApiRequest(genReq);
552
555
  myRes = new ExpressResponseBridgeToDataApiResponse(origRes, req, this.options.error);
553
- _a.label = 1;
554
- case 1:
555
- _a.trys.push([1, 3, , 4]);
556
+ if (!remult_static_js_1.remultStatic.asyncContext.isInInitRequest()) return [3 /*break*/, 2];
557
+ return [4 /*yield*/, what(remult_static_js_1.remultStatic.asyncContext.getStore().remult, myReq, myRes, genReq, origRes, req)];
558
+ case 1: return [2 /*return*/, _a.sent()];
559
+ case 2:
560
+ _a.trys.push([2, 4, , 5]);
556
561
  return [4 /*yield*/, this.runWithRemult(function (remult) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
557
562
  var user;
558
563
  return tslib_1.__generator(this, function (_a) {
559
564
  switch (_a.label) {
560
565
  case 0:
561
- if (!req) return [3 /*break*/, 5];
566
+ if (!req) return [3 /*break*/, 8];
567
+ remult_static_js_1.remultStatic.asyncContext.setInInitRequest(true);
568
+ _a.label = 1;
569
+ case 1:
570
+ _a.trys.push([1, , 7, 8]);
562
571
  user = void 0;
563
- if (!this.options.getUser) return [3 /*break*/, 2];
572
+ if (!this.options.getUser) return [3 /*break*/, 3];
564
573
  return [4 /*yield*/, this.options.getUser(req)];
565
- case 1:
566
- user = _a.sent();
567
- return [3 /*break*/, 3];
568
574
  case 2:
575
+ user = _a.sent();
576
+ return [3 /*break*/, 4];
577
+ case 3:
569
578
  user = req['user'];
570
579
  if (!user)
571
580
  user = req['auth'];
572
- _a.label = 3;
573
- case 3:
581
+ _a.label = 4;
582
+ case 4:
574
583
  if (user)
575
584
  remult.user = user;
576
- if (!this.options.initRequest) return [3 /*break*/, 5];
585
+ if (!this.options.initRequest) return [3 /*break*/, 6];
577
586
  return [4 /*yield*/, this.options.initRequest(req, {
578
587
  remult: remult,
579
588
  get liveQueryStorage() {
@@ -583,24 +592,28 @@ var RemultServerImplementation = /** @class */ (function () {
583
592
  remult.liveQueryStorage = value;
584
593
  },
585
594
  })];
586
- case 4:
595
+ case 5:
587
596
  _a.sent();
588
- _a.label = 5;
589
- case 5: return [4 /*yield*/, what(remult, myReq, myRes, genReq, origRes, req)];
590
- case 6:
597
+ _a.label = 6;
598
+ case 6: return [3 /*break*/, 8];
599
+ case 7:
600
+ remult_static_js_1.remultStatic.asyncContext.setInInitRequest(false);
601
+ return [7 /*endfinally*/];
602
+ case 8: return [4 /*yield*/, what(remult, myReq, myRes, genReq, origRes, req)];
603
+ case 9:
591
604
  _a.sent();
592
605
  return [2 /*return*/];
593
606
  }
594
607
  });
595
608
  }); })];
596
- case 2:
597
- _a.sent();
598
- return [3 /*break*/, 4];
599
609
  case 3:
610
+ _a.sent();
611
+ return [3 /*break*/, 5];
612
+ case 4:
600
613
  err_1 = _a.sent();
601
614
  myRes.error(err_1, undefined);
602
- return [3 /*break*/, 4];
603
- case 4: return [2 /*return*/];
615
+ return [3 /*break*/, 5];
616
+ case 5: return [2 /*return*/];
604
617
  }
605
618
  });
606
619
  }); };
package/src/context.d.ts CHANGED
@@ -8,9 +8,17 @@ export declare class RemultAsyncLocalStorage {
8
8
  private readonly remultObjectStorage;
9
9
  static enable(): void;
10
10
  static disable(): void;
11
- constructor(remultObjectStorage: RemultAsyncLocalStorageCore<Remult>);
11
+ constructor(remultObjectStorage: RemultAsyncLocalStorageCore<{
12
+ remult: Remult;
13
+ inInitRequest?: boolean;
14
+ }>);
12
15
  run<T>(remult: Remult, callback: (remult: Remult) => Promise<T>): Promise<T>;
13
- getRemult(): Remult;
16
+ isInInitRequest(): boolean;
17
+ setInInitRequest(val: boolean): void;
18
+ getStore(): {
19
+ remult: Remult;
20
+ inInitRequest?: boolean;
21
+ };
14
22
  }
15
23
  export type RemultAsyncLocalStorageCore<T> = {
16
24
  run<R>(store: T, callback: () => Promise<R>): Promise<R>;
@@ -195,5 +203,5 @@ export interface itemChange {
195
203
  }
196
204
  export declare function doTransaction(remult: Remult, what: (dp: DataProvider) => Promise<void>): Promise<void>;
197
205
  export declare function withRemult<T>(callback: (remult: any) => Promise<T>, options?: {
198
- dataProvider?: DataProvider;
206
+ dataProvider?: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>);
199
207
  }): Promise<T>;
package/src/context.js CHANGED
@@ -11,15 +11,16 @@ var server_action_info_js_1 = require("./server-action-info.js");
11
11
  var buildRestDataProvider_js_1 = require("./buildRestDataProvider.js");
12
12
  var relationInfoMember_js_1 = require("./remult3/relationInfoMember.js");
13
13
  var remult_static_js_1 = require("./remult-static.js");
14
+ var initDataProvider_1 = require("../server/initDataProvider");
14
15
  var RemultAsyncLocalStorage = /** @class */ (function () {
15
16
  function RemultAsyncLocalStorage(remultObjectStorage) {
16
17
  this.remultObjectStorage = remultObjectStorage;
17
18
  }
18
19
  RemultAsyncLocalStorage.enable = function () {
19
20
  remult_static_js_1.remultStatic.remultFactory = function () {
20
- var r = remult_static_js_1.remultStatic.asyncContext.getRemult();
21
+ var r = remult_static_js_1.remultStatic.asyncContext.getStore();
21
22
  if (r)
22
- return r;
23
+ return r.remult;
23
24
  else
24
25
  throw new Error('remult object was requested outside of a valid context, try running it within initApi or a remult request cycle');
25
26
  };
@@ -31,7 +32,7 @@ var RemultAsyncLocalStorage = /** @class */ (function () {
31
32
  return tslib_1.__awaiter(this, void 0, void 0, function () {
32
33
  return tslib_1.__generator(this, function (_a) {
33
34
  if (this.remultObjectStorage) {
34
- return [2 /*return*/, this.remultObjectStorage.run(remult, function () { return callback(remult); })];
35
+ return [2 /*return*/, this.remultObjectStorage.run({ remult: remult }, function () { return callback(remult); })];
35
36
  }
36
37
  else
37
38
  return [2 /*return*/, callback(remult)];
@@ -39,7 +40,18 @@ var RemultAsyncLocalStorage = /** @class */ (function () {
39
40
  });
40
41
  });
41
42
  };
42
- RemultAsyncLocalStorage.prototype.getRemult = function () {
43
+ RemultAsyncLocalStorage.prototype.isInInitRequest = function () {
44
+ var _a, _b;
45
+ return (_b = (_a = this.remultObjectStorage) === null || _a === void 0 ? void 0 : _a.getStore()) === null || _b === void 0 ? void 0 : _b.inInitRequest;
46
+ };
47
+ RemultAsyncLocalStorage.prototype.setInInitRequest = function (val) {
48
+ var _a;
49
+ var store = (_a = this.remultObjectStorage) === null || _a === void 0 ? void 0 : _a.getStore();
50
+ if (!store)
51
+ return;
52
+ store.inInitRequest = val;
53
+ };
54
+ RemultAsyncLocalStorage.prototype.getStore = function () {
43
55
  if (!this.remultObjectStorage) {
44
56
  throw new Error("can't use static remult in this environment, `async_hooks` were not initialized");
45
57
  }
@@ -455,9 +467,22 @@ var transactionLiveQueryPublisher = /** @class */ (function () {
455
467
  return transactionLiveQueryPublisher;
456
468
  }());
457
469
  function withRemult(callback, options) {
458
- var remult = new Remult();
459
- if (options === null || options === void 0 ? void 0 : options.dataProvider)
460
- remult.dataProvider = options.dataProvider;
461
- return remult_static_js_1.remultStatic.asyncContext.run(remult, function (r) { return callback(r); });
470
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
471
+ var remult, _a;
472
+ var _this = this;
473
+ return tslib_1.__generator(this, function (_b) {
474
+ switch (_b.label) {
475
+ case 0:
476
+ remult = new Remult();
477
+ _a = remult;
478
+ return [4 /*yield*/, (0, initDataProvider_1.initDataProvider)(options === null || options === void 0 ? void 0 : options.dataProvider, true, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
479
+ return [2 /*return*/, remult.dataProvider];
480
+ }); }); })];
481
+ case 1:
482
+ _a.dataProvider = _b.sent();
483
+ return [2 /*return*/, remult_static_js_1.remultStatic.asyncContext.run(remult, function (r) { return callback(r); })];
484
+ }
485
+ });
486
+ });
462
487
  }
463
488
  exports.withRemult = withRemult;
@@ -6,7 +6,8 @@ export interface JsonEntityStorage {
6
6
  }
7
7
  export declare class JsonDataProvider implements DataProvider {
8
8
  private storage;
9
- constructor(storage: JsonEntityStorage);
9
+ private formatted;
10
+ constructor(storage: JsonEntityStorage, formatted?: boolean);
10
11
  getEntityDataProvider(entity: EntityMetadata): EntityDataProvider;
11
12
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
12
13
  }
@@ -4,11 +4,13 @@ exports.JsonDataProvider = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var array_entity_data_provider_js_1 = require("./array-entity-data-provider.js");
6
6
  var JsonDataProvider = /** @class */ (function () {
7
- function JsonDataProvider(storage) {
7
+ function JsonDataProvider(storage, formatted) {
8
+ if (formatted === void 0) { formatted = false; }
8
9
  this.storage = storage;
10
+ this.formatted = formatted;
9
11
  }
10
12
  JsonDataProvider.prototype.getEntityDataProvider = function (entity) {
11
- return new JsonEntityDataProvider(entity, this.storage);
13
+ return new JsonEntityDataProvider(entity, this.storage, this.formatted);
12
14
  };
13
15
  JsonDataProvider.prototype.transaction = function (action) {
14
16
  return tslib_1.__awaiter(this, void 0, void 0, function () {
@@ -26,9 +28,10 @@ var JsonDataProvider = /** @class */ (function () {
26
28
  }());
27
29
  exports.JsonDataProvider = JsonDataProvider;
28
30
  var JsonEntityDataProvider = /** @class */ (function () {
29
- function JsonEntityDataProvider(entity, helper) {
31
+ function JsonEntityDataProvider(entity, helper, formatted) {
30
32
  this.entity = entity;
31
33
  this.helper = helper;
34
+ this.formatted = formatted;
32
35
  this.p = Promise.resolve();
33
36
  }
34
37
  JsonEntityDataProvider.prototype.loadEntityData = function (what) {
@@ -48,12 +51,14 @@ var JsonEntityDataProvider = /** @class */ (function () {
48
51
  if (s)
49
52
  data = JSON.parse(s);
50
53
  dp = new array_entity_data_provider_js_1.ArrayEntityDataProvider(this.entity, function () { return data; });
51
- return [2 /*return*/, what(dp, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
52
- switch (_a.label) {
53
- case 0: return [4 /*yield*/, this.helper.setItem(dbName, JSON.stringify(data, undefined, 2))];
54
- case 1: return [2 /*return*/, _a.sent()];
55
- }
56
- }); }); })];
54
+ return [2 /*return*/, what(dp, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
55
+ return tslib_1.__generator(this, function (_a) {
56
+ switch (_a.label) {
57
+ case 0: return [4 /*yield*/, this.helper.setItem(dbName, JSON.stringify(data, undefined, this.formatted ? 2 : undefined))];
58
+ case 1: return [2 /*return*/, _a.sent()];
59
+ }
60
+ });
61
+ }); })];
57
62
  }
58
63
  });
59
64
  });
@@ -14,7 +14,6 @@ var LiveQueryClient = /** @class */ (function () {
14
14
  this.getUserId = getUserId;
15
15
  this.queries = new Map();
16
16
  this.channels = new Map();
17
- this.keepAliveMs = 1000;
18
17
  }
19
18
  LiveQueryClient.prototype.wrapMessageHandling = function (handleMessage) {
20
19
  var x = this.apiProvider().wrapMessageHandling;
@@ -88,7 +87,7 @@ var LiveQueryClient = /** @class */ (function () {
88
87
  });
89
88
  });
90
89
  };
91
- LiveQueryClient.prototype._actuallyClose = function () {
90
+ LiveQueryClient.prototype.closeIfNoListeners = function () {
92
91
  if (this.client)
93
92
  if (this.queries.size === 0 && this.channels.size === 0) {
94
93
  this.runPromise(this.client.then(function (x) { return x.close(); }));
@@ -97,12 +96,6 @@ var LiveQueryClient = /** @class */ (function () {
97
96
  this.interval = undefined;
98
97
  }
99
98
  };
100
- LiveQueryClient.prototype.closeIfNoListeners = function () {
101
- var _this = this;
102
- setTimeout(function () {
103
- _this._actuallyClose();
104
- }, this.keepAliveMs);
105
- };
106
99
  LiveQueryClient.prototype.subscribe = function (repo, options, listener) {
107
100
  var _this = this;
108
101
  var alive = true;
@@ -196,8 +189,7 @@ var LiveQueryClient = /** @class */ (function () {
196
189
  try {
197
190
  for (_a = tslib_1.__values(this.queries.values()), _b = _a.next(); !_b.done; _b = _a.next()) {
198
191
  q = _b.value;
199
- if (q.gotAnyResult)
200
- ids.push(q.queryChannel);
192
+ ids.push(q.queryChannel);
201
193
  }
202
194
  }
203
195
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
@@ -12,7 +12,6 @@ var LiveQuerySubscriber = /** @class */ (function () {
12
12
  function LiveQuerySubscriber(repo, query, userId) {
13
13
  this.repo = repo;
14
14
  this.query = query;
15
- this.gotAnyResult = false;
16
15
  this.unsubscribe = function () { };
17
16
  this.defaultQueryState = [];
18
17
  this.listeners = [];
@@ -29,9 +28,7 @@ var LiveQuerySubscriber = /** @class */ (function () {
29
28
  var items;
30
29
  return tslib_1.__generator(this, function (_a) {
31
30
  switch (_a.label) {
32
- case 0:
33
- this.gotAnyResult = true;
34
- return [4 /*yield*/, (0, repository_internals_js_1.getRepositoryInternals)(this.repo)._fromJsonArray(result, this.query.options)];
31
+ case 0: return [4 /*yield*/, (0, repository_internals_js_1.getRepositoryInternals)(this.repo)._fromJsonArray(result, this.query.options)];
35
32
  case 1:
36
33
  items = _a.sent();
37
34
  this.forListeners(function (listener) {
@@ -1,5 +1,6 @@
1
1
  import type { ClassType } from '../classType.js';
2
2
  import type { ClassHelper, Remult, RemultAsyncLocalStorage } from './context.js';
3
+ import { DataProvider } from './data-interfaces';
3
4
  import type { columnInfo } from './remult3/columnInfo.js';
4
5
  export declare const remultStatic: {
5
6
  defaultRemultFactory: () => Remult;
@@ -19,6 +20,7 @@ export declare const remultStatic: {
19
20
  };
20
21
  };
21
22
  captionTransformer: any;
23
+ defaultDataProvider: () => Promise<DataProvider>;
22
24
  };
23
25
  export declare function defaultFactory(): Remult;
24
26
  export declare function resetFactory(): void;
@@ -22,6 +22,7 @@ var x = {
22
22
  }); },
23
23
  },
24
24
  captionTransformer: undefined,
25
+ defaultDataProvider: function () { return undefined; },
25
26
  };
26
27
  if ((typeof process !== 'undefined' &&
27
28
  process.env['IGNORE_GLOBAL_REMULT_IN_TESTS']) ||
@@ -4,15 +4,17 @@ exports.flags = void 0;
4
4
  exports.flags = {
5
5
  error500RetryCount: 4,
6
6
  };
7
- //y2 - soft-delete-discussion https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
8
7
  //y1 - live query with count #436
9
- //y1 - live query errort that appears in tests but I can't understand why - `open connection error `
8
+ //y1 - https://github.com/remult/remult/discussions/438
9
+ //p1 - discuss next auth withRemult paradox
10
+ //p1 - maybe the default withRemult should by default use the data provider set by the remultExpress
11
+ //p1 - withRemult to support the full range of data provider.
10
12
  //y1 TODO - In the esm version of our tutorial - the imports are automatically .ts and not .js in react and not in vue
11
13
  //y1 TODO - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
12
14
  //y1 TODO - readonly key: keyof MembersOnly<entityType> & string
13
15
  //y1 - talk about insert / update / delete with relations
14
16
  /*
15
- repo(Order).insert({},{
17
+ repo(Order).insert({},{
16
18
  relations:{
17
19
  orderItems:[{},{},{}]
18
20
  }
@@ -20,13 +22,16 @@ exports.flags = {
20
22
  */
21
23
  //y1 - repo batch - for multiple operations:
22
24
  /*
23
- const result = await repo.batch(x=>({
24
- data:x.find(),
25
- count:x.count()
26
- }))
25
+ const result = await repo.batch(x=>({
26
+ data:x.find(),
27
+ count:x.count()
28
+ }))
27
29
  */
30
+ //p1 - consider in json storage, to store the json without spaces
28
31
  //p1 - consider upsert (where,set)
29
- //p1 - wait a second to close stream
32
+ //y1 - wait a second to close stream -see pr
33
+ //p1 - Consider enforcing serial operations on JSON database to prevent data loss
34
+ //y2 - soft-delete-discussion https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
30
35
  //p1 - prepare the createEntity discussion
31
36
  //p1 - return error on connection error
32
37
  //p1 - article on displayValue including it's definition for entities that is used in relations
@@ -84,6 +89,8 @@ exports.flags = {
84
89
  //p1 - when a tasks table exists in a different schema - we get many errors
85
90
  //p1 - live query with include
86
91
  //p1 - adjust angular tutorial starter kit for latest angular (as is in tutorial)
92
+ //y2 - Fix problem with promise all in sql expression recurssion - when using PromiseAll in row relation loading, some sql expressions appear is recursion call even if they are not
93
+ //p2 - when subscribe is forbidden - the query still runs after the renew process
87
94
  //p2 - 'update tasks set where id = $1
88
95
  //p2 - type metadata.key - to keyof entity - based on cwis input
89
96
  //y2 - remove __dirname from tutorials