remult 0.19.0 → 0.19.2-exp.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.
@@ -14,10 +14,9 @@ export declare class DataProviderLiveQueryStorage implements LiveQueryStorage, S
14
14
  }) => Promise<void>): Promise<void>;
15
15
  keepAliveAndReturnUnknownQueryIds(queryIds: string[]): Promise<string[]>;
16
16
  }
17
- declare class LiveQueryStorageEntity extends EntityBase {
17
+ export declare class LiveQueryStorageEntity extends EntityBase {
18
18
  id: string;
19
19
  entityKey: string;
20
20
  data: any;
21
21
  lastUsedIso: string;
22
22
  }
23
- export {};
@@ -53,7 +53,9 @@ export class DataProviderLiveQueryStorage {
53
53
  return queryIds;
54
54
  }
55
55
  }
56
- let LiveQueryStorageEntity = class LiveQueryStorageEntity extends EntityBase {
56
+ let LiveQueryStorageEntity =
57
+ /*@internal */
58
+ class LiveQueryStorageEntity extends EntityBase {
57
59
  constructor() {
58
60
  super(...arguments);
59
61
  this.id = '';
@@ -81,5 +83,7 @@ LiveQueryStorageEntity = __decorate([
81
83
  Entity(undefined, {
82
84
  dbName: 'remult_live_query_storage'
83
85
  })
86
+ /*@internal */
84
87
  ], LiveQueryStorageEntity);
88
+ export { LiveQueryStorageEntity };
85
89
  allEntities.splice(allEntities.indexOf(LiveQueryStorageEntity), 1);
@@ -11,6 +11,7 @@ export interface PostgresClient extends PostgresCommandSource {
11
11
  }
12
12
  export declare class PostgresDataProvider implements SqlImplementation {
13
13
  private pool;
14
+ supportsJsonColumnType: boolean;
14
15
  static getDb(remult?: Remult): ClientBase;
15
16
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
16
17
  getLimitSqlSyntax(limit: number, offset: number): string;
@@ -5,6 +5,7 @@ import { SqlDatabase } from '../src/data-providers/sql-database';
5
5
  export class PostgresDataProvider {
6
6
  constructor(pool) {
7
7
  this.pool = pool;
8
+ this.supportsJsonColumnType = true;
8
9
  }
9
10
  static getDb(remult) {
10
11
  const sql = SqlDatabase.getDb(remult);
@@ -25,5 +25,5 @@ export declare class KnexSchemaBuilder {
25
25
  additionalWhere: string;
26
26
  constructor(knex: Knex);
27
27
  }
28
- export declare function buildColumn(x: FieldMetadata, dbName: string, b: Knex.CreateTableBuilder): void;
28
+ export declare function buildColumn(x: FieldMetadata, dbName: string, b: Knex.CreateTableBuilder, supportsJson?: boolean): void;
29
29
  export declare function createKnexDataProvider(config: Knex.Config): Promise<KnexDataProvider>;
@@ -17,6 +17,13 @@ export class KnexDataProvider {
17
17
  return r.knex;
18
18
  }
19
19
  getEntityDataProvider(entity) {
20
+ if (!supportsJson(this.knex))
21
+ for (const f of entity.fields.toArray()) {
22
+ if (f.valueConverter.fieldTypeInDb === "json") {
23
+ //@ts-ignore
24
+ f.valueConverter = { ...f.valueConverter, toDb: ValueConverters.JsonString.toDb, fromDb: ValueConverters.JsonString.fromDb };
25
+ }
26
+ }
20
27
  return new KnexEntityDataProvider(entity, this.knex);
21
28
  }
22
29
  async transaction(action) {
@@ -318,7 +325,7 @@ export class KnexSchemaBuilder {
318
325
  if (isAutoIncrement(x))
319
326
  b.increments(cols.get(x).name);
320
327
  else {
321
- buildColumn(x, cols.get(x).name, b);
328
+ buildColumn(x, cols.get(x).name, b, supportsJson(this.knex));
322
329
  if (x == entity.idMetadata.field)
323
330
  b.primary([cols.get(x).name]);
324
331
  }
@@ -335,7 +342,7 @@ export class KnexSchemaBuilder {
335
342
  let colName = e.$dbNameOf(col);
336
343
  if (!await this.knex.schema.hasColumn(e.$entityName, colName)) {
337
344
  await logSql(this.knex.schema.alterTable(e.$entityName, b => {
338
- buildColumn(col, colName, b);
345
+ buildColumn(col, colName, b, supportsJson(this.knex));
339
346
  }));
340
347
  }
341
348
  }
@@ -355,7 +362,13 @@ export class KnexSchemaBuilder {
355
362
  }
356
363
  //@internal
357
364
  KnexSchemaBuilder.logToConsole = true;
358
- export function buildColumn(x, dbName, b) {
365
+ function supportsJson(knex) {
366
+ const client = knex.client.config.client;
367
+ if (client?.includes("sqlite3") || client?.includes("mssql"))
368
+ return false;
369
+ return true;
370
+ }
371
+ export function buildColumn(x, dbName, b, supportsJson = true) {
359
372
  if (x.valueType == Number) {
360
373
  if (!x.valueConverter.fieldTypeInDb) {
361
374
  let c = b.decimal(dbName);
@@ -395,6 +408,11 @@ export function buildColumn(x, dbName, b) {
395
408
  c.defaultTo(0).notNullable();
396
409
  }
397
410
  }
411
+ else if (x.valueConverter.fieldTypeInDb == "json")
412
+ if (supportsJson)
413
+ b.json(dbName);
414
+ else
415
+ b.text(dbName);
398
416
  else
399
417
  b.specificType(dbName, x.valueConverter.fieldTypeInDb);
400
418
  }
@@ -174,9 +174,9 @@ export class RestDataProviderHttpProviderUsingFetch {
174
174
  }));
175
175
  }
176
176
  myFetch(url, options) {
177
- const headers = {
178
- "Content-type": "application/json"
179
- };
177
+ const headers = {};
178
+ if (options?.body)
179
+ headers["Content-type"] = "application/json";
180
180
  if (typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof (window.document.cookie !== 'undefined'))
181
181
  for (const cookie of window.document.cookie.split(';')) {
182
182
  if (cookie.trim().startsWith('XSRF-TOKEN=')) {
@@ -4,6 +4,7 @@ import { customDatabaseFilterToken, Filter } from '../filter/filter-interfaces';
4
4
  import { Sort } from '../sort';
5
5
  import { getRepository } from "../remult3";
6
6
  import { RemultProxy } from "../remult-proxy";
7
+ import { ValueConverters } from "../valueConverters";
7
8
  // @dynamic
8
9
  export class SqlDatabase {
9
10
  constructor(sql) {
@@ -31,6 +32,14 @@ export class SqlDatabase {
31
32
  await this.sql.ensureSchema(entities);
32
33
  }
33
34
  getEntityDataProvider(entity) {
35
+ if (!this.sql.supportsJsonColumnType) {
36
+ for (const f of entity.fields.toArray()) {
37
+ if (f.valueConverter.fieldTypeInDb === "json") {
38
+ //@ts-ignore
39
+ f.valueConverter = { ...f.valueConverter, toDb: ValueConverters.JsonString.toDb, fromDb: ValueConverters.JsonString.fromDb };
40
+ }
41
+ }
42
+ }
34
43
  return new ActualSQLServerDataProvider(entity, this, async (dbName) => {
35
44
  if (this.createdEntities.indexOf(dbName.$entityName) < 0) {
36
45
  this.createdEntities.push(dbName.$entityName);
@@ -6,7 +6,11 @@ export interface EntityOptions<entityType = any> {
6
6
  caption?: string;
7
7
  /**
8
8
  * Determines if this Entity is available for get requests using Rest Api
9
- * @see [allowed](http://remult.dev/docs/allowed.html)*/
9
+ * @description
10
+ * Determines if one has any access to the data of an entity.
11
+ * @see [allowed](http://remult.dev/docs/allowed.html)
12
+ * @see to restrict data based on a criteria, use [apiPrefilter](https://remult.dev/docs/ref_entity.html#apiprefilter)
13
+ * */
10
14
  allowApiRead?: Allowed;
11
15
  /**
12
16
  * Determines if this entity can be updated through the api.
@@ -21,10 +25,15 @@ export interface EntityOptions<entityType = any> {
21
25
  /** sets the `allowApiUpdate`, `allowApiDelete` and `allowApiInsert` properties in a single set */
22
26
  allowApiCrud?: Allowed;
23
27
  /** A filter that determines which rows can be queries using the api.
28
+ * @description
29
+ * Use apiPrefilter in cases where you to restrict data based on user profile
24
30
  * @example
25
31
  * apiPrefilter: { archive:false }
26
32
  *
33
+ * @example
34
+ * apiPrefilter: ()=> remult.isAllowed("admin")?{}:{ archive:false }
27
35
  * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
36
+ *
28
37
  */
29
38
  apiPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
30
39
  /** A filter that will be used for all queries from this entity both from the API and from within the backend.
@@ -226,7 +226,11 @@ declare class EntityFullInfo<T> implements EntityMetadata<T> {
226
226
  }
227
227
  export declare function FieldType<valueType = any>(...options: (FieldOptions<any, valueType> | ((options: FieldOptions<any, valueType>, remult: Remult) => void))[]): (target: any) => any;
228
228
  export declare class Fields {
229
+ /**
230
+ * Stored as a JSON.stringify - to store as json use Fields.json
231
+ */
229
232
  static object<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
233
+ static json<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
230
234
  static dateOnly<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
231
235
  static date<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
232
236
  static integer<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
@@ -1444,9 +1444,19 @@ export function FieldType(...options) {
1444
1444
  };
1445
1445
  }
1446
1446
  export class Fields {
1447
+ /**
1448
+ * Stored as a JSON.stringify - to store as json use Fields.json
1449
+ */
1447
1450
  static object(...options) {
1448
1451
  return Field(undefined, ...options);
1449
1452
  }
1453
+ static json(...options) {
1454
+ return Field(undefined, {
1455
+ valueConverter: {
1456
+ fieldTypeInDb: "json"
1457
+ }
1458
+ }, ...options);
1459
+ }
1450
1460
  static dateOnly(...options) {
1451
1461
  return Field(() => Date, {
1452
1462
  valueConverter: ValueConverters.DateOnly
@@ -19,7 +19,7 @@ import { Validators } from "../validators";
19
19
  import { Status } from "../tests/testModel/models";
20
20
  import { IdEntity } from "../id-entity";
21
21
  import { describeClass } from "../remult3/DecoratorReplacer";
22
- import { DataProviderLiveQueryStorage } from "../../live-query/data-provider-live-query-storage";
22
+ import { DataProviderLiveQueryStorage, LiveQueryStorageEntity } from "../../live-query/data-provider-live-query-storage";
23
23
  import { v4 as uuid } from 'uuid';
24
24
  testAll("what", async ({ remult, createEntity }) => {
25
25
  await (await createEntity(stam)).create({ id: 1, title: 'noam' }).save();
@@ -769,7 +769,8 @@ testAll("test date", async ({ createEntity }) => {
769
769
  let item = await r.findFirst();
770
770
  expect(item.d.getFullYear()).toBe(1976);
771
771
  }, false);
772
- testAll("test live query storage", async ({ db, remult }) => {
772
+ testAll("test live query storage", async ({ db, remult, createEntity }) => {
773
+ await createEntity(LiveQueryStorageEntity);
773
774
  var x = new DataProviderLiveQueryStorage(db);
774
775
  if (db.ensureSchema)
775
776
  await x.ensureSchema();
@@ -801,6 +802,7 @@ testAll("test contains with names with casing", async ({ createEntity }) => {
801
802
  exclude: [TestDbs.mongo]
802
803
  });
803
804
  testAll("test live query storage", async (x) => {
805
+ await x.createEntity(LiveQueryStorageEntity);
804
806
  const s = new DataProviderLiveQueryStorage(x.db);
805
807
  await s.ensureSchema();
806
808
  const entityKey = "ek";
@@ -813,3 +815,79 @@ testAll("test live query storage", async (x) => {
813
815
  await s.remove(id);
814
816
  await s.remove(id);
815
817
  }, false, { exclude: [TestDbs.restDataProvider] });
818
+ testAll("test json structure using object", async ({ createEntity }) => {
819
+ const e = class {
820
+ constructor() {
821
+ this.a = 0;
822
+ }
823
+ };
824
+ describeClass(e, Entity("testJsonStructure", { allowApiCrud: true }), {
825
+ a: Fields.number(),
826
+ person: Fields.object()
827
+ });
828
+ const r = await createEntity(e);
829
+ await r.insert({ a: 1, person: { firstName: "noam", lastName: "honig" } });
830
+ let item = await r.findFirst();
831
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
832
+ }, false);
833
+ let testObject = class testObject {
834
+ constructor() {
835
+ this.id = 0;
836
+ this.person = { firstName: "noam", lastName: "honig" };
837
+ }
838
+ };
839
+ __decorate([
840
+ Fields.integer(),
841
+ __metadata("design:type", Object)
842
+ ], testObject.prototype, "id", void 0);
843
+ __decorate([
844
+ Fields.object(),
845
+ __metadata("design:type", Object)
846
+ ], testObject.prototype, "person", void 0);
847
+ testObject = __decorate([
848
+ Entity("testObject", { allowApiCrud: true })
849
+ ], testObject);
850
+ testAll("test object entity", async ({ createEntity }) => {
851
+ const r = await createEntity(testObject);
852
+ await r.insert({ id: 1, person: { firstName: "noam", lastName: "honig" } });
853
+ let item = await r.findFirst();
854
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
855
+ }, false);
856
+ let testObjectJson = class testObjectJson {
857
+ constructor() {
858
+ this.id = 0;
859
+ this.person = { firstName: "noam", lastName: "honig" };
860
+ }
861
+ };
862
+ __decorate([
863
+ Fields.integer(),
864
+ __metadata("design:type", Object)
865
+ ], testObjectJson.prototype, "id", void 0);
866
+ __decorate([
867
+ Fields.json(),
868
+ __metadata("design:type", Object)
869
+ ], testObjectJson.prototype, "person", void 0);
870
+ testObjectJson = __decorate([
871
+ Entity("testObjectJson", { allowApiCrud: true })
872
+ ], testObjectJson);
873
+ testAll("test object entity", async ({ createEntity }) => {
874
+ const r = await createEntity(testObjectJson);
875
+ await r.insert({ id: 1, person: { firstName: "noam", lastName: "honig" } });
876
+ let item = await r.findFirst();
877
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
878
+ }, false);
879
+ testAll("test json structure", async ({ createEntity }) => {
880
+ const e = class {
881
+ constructor() {
882
+ this.a = 0;
883
+ }
884
+ };
885
+ describeClass(e, Entity("testJsonFieldType", { allowApiCrud: true }), {
886
+ a: Fields.number(),
887
+ person: Fields.json()
888
+ });
889
+ const r = await createEntity(e);
890
+ await r.insert({ a: 1, person: { firstName: "noam", lastName: "honig" } });
891
+ let item = await r.findFirst();
892
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
893
+ }, false);
@@ -5,6 +5,7 @@ export interface SqlImplementation {
5
5
  transaction(action: (sql: SqlImplementation) => Promise<void>): Promise<void>;
6
6
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
7
7
  ensureSchema?(entities: EntityMetadata[]): Promise<void>;
8
+ supportsJsonColumnType?: boolean;
8
9
  }
9
10
  export interface SqlCommand extends SqlCommandWithParameters {
10
11
  execute(sql: string): Promise<SqlResult>;
@@ -14,10 +14,9 @@ export declare class DataProviderLiveQueryStorage implements LiveQueryStorage, S
14
14
  }) => Promise<void>): Promise<void>;
15
15
  keepAliveAndReturnUnknownQueryIds(queryIds: string[]): Promise<string[]>;
16
16
  }
17
- declare class LiveQueryStorageEntity extends EntityBase {
17
+ export declare class LiveQueryStorageEntity extends EntityBase {
18
18
  id: string;
19
19
  entityKey: string;
20
20
  data: any;
21
21
  lastUsedIso: string;
22
22
  }
23
- export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DataProviderLiveQueryStorage = void 0;
3
+ exports.LiveQueryStorageEntity = exports.DataProviderLiveQueryStorage = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var initDataProvider_1 = require("../server/initDataProvider");
6
6
  var context_1 = require("../src/context");
@@ -223,6 +223,7 @@ var DataProviderLiveQueryStorage = /** @class */ (function () {
223
223
  exports.DataProviderLiveQueryStorage = DataProviderLiveQueryStorage;
224
224
  var LiveQueryStorageEntity = /** @class */ (function (_super) {
225
225
  tslib_1.__extends(LiveQueryStorageEntity, _super);
226
+ /*@internal */
226
227
  function LiveQueryStorageEntity() {
227
228
  var _this = _super !== null && _super.apply(this, arguments) || this;
228
229
  _this.id = '';
@@ -250,7 +251,9 @@ var LiveQueryStorageEntity = /** @class */ (function (_super) {
250
251
  remult3_1.Entity(undefined, {
251
252
  dbName: 'remult_live_query_storage'
252
253
  })
254
+ /*@internal */
253
255
  ], LiveQueryStorageEntity);
254
256
  return LiveQueryStorageEntity;
255
257
  }(remult3_1.EntityBase));
258
+ exports.LiveQueryStorageEntity = LiveQueryStorageEntity;
256
259
  context_1.allEntities.splice(context_1.allEntities.indexOf(LiveQueryStorageEntity), 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.19.0",
3
+ "version": "0.19.2-exp.0",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -11,6 +11,7 @@ export interface PostgresClient extends PostgresCommandSource {
11
11
  }
12
12
  export declare class PostgresDataProvider implements SqlImplementation {
13
13
  private pool;
14
+ supportsJsonColumnType: boolean;
14
15
  static getDb(remult?: Remult): ClientBase;
15
16
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
16
17
  getLimitSqlSyntax(limit: number, offset: number): string;
@@ -9,6 +9,7 @@ var sql_database_1 = require("../src/data-providers/sql-database");
9
9
  var PostgresDataProvider = /** @class */ (function () {
10
10
  function PostgresDataProvider(pool) {
11
11
  this.pool = pool;
12
+ this.supportsJsonColumnType = true;
12
13
  }
13
14
  PostgresDataProvider.getDb = function (remult) {
14
15
  var sql = sql_database_1.SqlDatabase.getDb(remult);
@@ -25,5 +25,5 @@ export declare class KnexSchemaBuilder {
25
25
  additionalWhere: string;
26
26
  constructor(knex: Knex);
27
27
  }
28
- export declare function buildColumn(x: FieldMetadata, dbName: string, b: Knex.CreateTableBuilder): void;
28
+ export declare function buildColumn(x: FieldMetadata, dbName: string, b: Knex.CreateTableBuilder, supportsJson?: boolean): void;
29
29
  export declare function createKnexDataProvider(config: Knex.Config): Promise<KnexDataProvider>;
@@ -21,6 +21,24 @@ var KnexDataProvider = /** @class */ (function () {
21
21
  return r.knex;
22
22
  };
23
23
  KnexDataProvider.prototype.getEntityDataProvider = function (entity) {
24
+ var e_1, _a;
25
+ if (!supportsJson(this.knex))
26
+ try {
27
+ for (var _b = tslib_1.__values(entity.fields.toArray()), _c = _b.next(); !_c.done; _c = _b.next()) {
28
+ var f = _c.value;
29
+ if (f.valueConverter.fieldTypeInDb === "json") {
30
+ //@ts-ignore
31
+ f.valueConverter = tslib_1.__assign(tslib_1.__assign({}, f.valueConverter), { toDb: valueConverters_1.ValueConverters.JsonString.toDb, fromDb: valueConverters_1.ValueConverters.JsonString.fromDb });
32
+ }
33
+ }
34
+ }
35
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
36
+ finally {
37
+ try {
38
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
39
+ }
40
+ finally { if (e_1) throw e_1.error; }
41
+ }
24
42
  return new KnexEntityDataProvider(entity, this.knex);
25
43
  };
26
44
  KnexDataProvider.prototype.transaction = function (action) {
@@ -139,7 +157,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
139
157
  KnexEntityDataProvider.prototype.find = function (options) {
140
158
  return tslib_1.__awaiter(this, void 0, void 0, function () {
141
159
  var e, cols, colKeys, _a, _b, x, query, br, r_1, r;
142
- var e_1, _c;
160
+ var e_2, _c;
143
161
  return tslib_1.__generator(this, function (_d) {
144
162
  switch (_d.label) {
145
163
  case 0: return [4 /*yield*/, this.init()];
@@ -158,12 +176,12 @@ var KnexEntityDataProvider = /** @class */ (function () {
158
176
  }
159
177
  }
160
178
  }
161
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
179
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
162
180
  finally {
163
181
  try {
164
182
  if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
165
183
  }
166
- finally { if (e_1) throw e_1.error; }
184
+ finally { if (e_2) throw e_2.error; }
167
185
  }
168
186
  query = this.knex(e.$entityName).select(cols);
169
187
  if (!(options === null || options === void 0 ? void 0 : options.where)) return [3 /*break*/, 3];
@@ -222,8 +240,8 @@ var KnexEntityDataProvider = /** @class */ (function () {
222
240
  };
223
241
  KnexEntityDataProvider.prototype.update = function (id, data) {
224
242
  return tslib_1.__awaiter(this, void 0, void 0, function () {
225
- var e, f, resultFilter, updateObject, _a, _b, x, v, key, e_2_1, where;
226
- var e_2, _c;
243
+ var e, f, resultFilter, updateObject, _a, _b, x, v, key, e_3_1, where;
244
+ var e_3, _c;
227
245
  return tslib_1.__generator(this, function (_d) {
228
246
  switch (_d.label) {
229
247
  case 0: return [4 /*yield*/, this.init()];
@@ -259,14 +277,14 @@ var KnexEntityDataProvider = /** @class */ (function () {
259
277
  return [3 /*break*/, 3];
260
278
  case 7: return [3 /*break*/, 10];
261
279
  case 8:
262
- e_2_1 = _d.sent();
263
- e_2 = { error: e_2_1 };
280
+ e_3_1 = _d.sent();
281
+ e_3 = { error: e_3_1 };
264
282
  return [3 /*break*/, 10];
265
283
  case 9:
266
284
  try {
267
285
  if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
268
286
  }
269
- finally { if (e_2) throw e_2.error; }
287
+ finally { if (e_3) throw e_3.error; }
270
288
  return [7 /*endfinally*/];
271
289
  case 10: return [4 /*yield*/, f.resolveWhere()];
272
290
  case 11:
@@ -302,8 +320,8 @@ var KnexEntityDataProvider = /** @class */ (function () {
302
320
  };
303
321
  KnexEntityDataProvider.prototype.insert = function (data) {
304
322
  return tslib_1.__awaiter(this, void 0, void 0, function () {
305
- var e, resultFilter, insertObject, _a, _b, x, v, key, e_3_1, insert, newId_1, result, result;
306
- var e_3, _c;
323
+ var e, resultFilter, insertObject, _a, _b, x, v, key, e_4_1, insert, newId_1, result, result;
324
+ var e_4, _c;
307
325
  var _this = this;
308
326
  return tslib_1.__generator(this, function (_d) {
309
327
  switch (_d.label) {
@@ -338,14 +356,14 @@ var KnexEntityDataProvider = /** @class */ (function () {
338
356
  return [3 /*break*/, 3];
339
357
  case 7: return [3 /*break*/, 10];
340
358
  case 8:
341
- e_3_1 = _d.sent();
342
- e_3 = { error: e_3_1 };
359
+ e_4_1 = _d.sent();
360
+ e_4 = { error: e_4_1 };
343
361
  return [3 /*break*/, 10];
344
362
  case 9:
345
363
  try {
346
364
  if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
347
365
  }
348
- finally { if (e_3) throw e_3.error; }
366
+ finally { if (e_4) throw e_4.error; }
349
367
  return [7 /*endfinally*/];
350
368
  case 10:
351
369
  insert = this.knex(e.$entityName).insert(insertObject);
@@ -386,8 +404,8 @@ var FilterConsumerBridgeToKnexRequest = /** @class */ (function () {
386
404
  }
387
405
  FilterConsumerBridgeToKnexRequest.prototype.resolveWhere = function () {
388
406
  return tslib_1.__awaiter(this, void 0, void 0, function () {
389
- var p, p_1, p_1_1, pr, e_4_1;
390
- var e_4, _a;
407
+ var p, p_1, p_1_1, pr, e_5_1;
408
+ var e_5, _a;
391
409
  return tslib_1.__generator(this, function (_b) {
392
410
  switch (_b.label) {
393
411
  case 0:
@@ -397,7 +415,7 @@ var FilterConsumerBridgeToKnexRequest = /** @class */ (function () {
397
415
  _b.label = 1;
398
416
  case 1:
399
417
  _b.trys.push([1, 6, 7, 8]);
400
- p_1 = (e_4 = void 0, tslib_1.__values(p)), p_1_1 = p_1.next();
418
+ p_1 = (e_5 = void 0, tslib_1.__values(p)), p_1_1 = p_1.next();
401
419
  _b.label = 2;
402
420
  case 2:
403
421
  if (!!p_1_1.done) return [3 /*break*/, 5];
@@ -411,14 +429,14 @@ var FilterConsumerBridgeToKnexRequest = /** @class */ (function () {
411
429
  return [3 /*break*/, 2];
412
430
  case 5: return [3 /*break*/, 8];
413
431
  case 6:
414
- e_4_1 = _b.sent();
415
- e_4 = { error: e_4_1 };
432
+ e_5_1 = _b.sent();
433
+ e_5 = { error: e_5_1 };
416
434
  return [3 /*break*/, 8];
417
435
  case 7:
418
436
  try {
419
437
  if (p_1_1 && !p_1_1.done && (_a = p_1.return)) _a.call(p_1);
420
438
  }
421
- finally { if (e_4) throw e_4.error; }
439
+ finally { if (e_5) throw e_5.error; }
422
440
  return [7 /*endfinally*/];
423
441
  case 8: return [3 /*break*/, 0];
424
442
  case 9: return [2 /*return*/, this.result];
@@ -432,8 +450,8 @@ var FilterConsumerBridgeToKnexRequest = /** @class */ (function () {
432
450
  FilterConsumerBridgeToKnexRequest.prototype.or = function (orElements) {
433
451
  var _this = this;
434
452
  this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
435
- var result, _loop_1, this_1, orElements_1, orElements_1_1, element, state_1, e_5_1;
436
- var e_5, _a;
453
+ var result, _loop_1, this_1, orElements_1, orElements_1_1, element, state_1, e_6_1;
454
+ var e_6, _a;
437
455
  return tslib_1.__generator(this, function (_b) {
438
456
  switch (_b.label) {
439
457
  case 0:
@@ -482,14 +500,14 @@ var FilterConsumerBridgeToKnexRequest = /** @class */ (function () {
482
500
  return [3 /*break*/, 2];
483
501
  case 5: return [3 /*break*/, 8];
484
502
  case 6:
485
- e_5_1 = _b.sent();
486
- e_5 = { error: e_5_1 };
503
+ e_6_1 = _b.sent();
504
+ e_6 = { error: e_6_1 };
487
505
  return [3 /*break*/, 8];
488
506
  case 7:
489
507
  try {
490
508
  if (orElements_1_1 && !orElements_1_1.done && (_a = orElements_1.return)) _a.call(orElements_1);
491
509
  }
492
- finally { if (e_5) throw e_5.error; }
510
+ finally { if (e_6) throw e_6.error; }
493
511
  return [7 /*endfinally*/];
494
512
  case 8:
495
513
  if (result.length > 0) {
@@ -584,8 +602,8 @@ var KnexSchemaBuilder = /** @class */ (function () {
584
602
  };
585
603
  KnexSchemaBuilder.prototype.ensureSchema = function (entities) {
586
604
  return tslib_1.__awaiter(this, void 0, void 0, function () {
587
- var entities_1, entities_1_1, entity, e, err_2, e_6_1;
588
- var e_6, _a;
605
+ var entities_1, entities_1_1, entity, e, err_2, e_7_1;
606
+ var e_7, _a;
589
607
  return tslib_1.__generator(this, function (_b) {
590
608
  switch (_b.label) {
591
609
  case 0:
@@ -620,14 +638,14 @@ var KnexSchemaBuilder = /** @class */ (function () {
620
638
  return [3 /*break*/, 1];
621
639
  case 9: return [3 /*break*/, 12];
622
640
  case 10:
623
- e_6_1 = _b.sent();
624
- e_6 = { error: e_6_1 };
641
+ e_7_1 = _b.sent();
642
+ e_7 = { error: e_7_1 };
625
643
  return [3 /*break*/, 12];
626
644
  case 11:
627
645
  try {
628
646
  if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
629
647
  }
630
- finally { if (e_6) throw e_6.error; }
648
+ finally { if (e_7) throw e_7.error; }
631
649
  return [7 /*endfinally*/];
632
650
  case 12: return [2 /*return*/];
633
651
  }
@@ -637,7 +655,8 @@ var KnexSchemaBuilder = /** @class */ (function () {
637
655
  KnexSchemaBuilder.prototype.createIfNotExist = function (entity) {
638
656
  return tslib_1.__awaiter(this, void 0, void 0, function () {
639
657
  var e, cols_1, _a, _b, f;
640
- var e_7, _c;
658
+ var e_8, _c;
659
+ var _this = this;
641
660
  return tslib_1.__generator(this, function (_d) {
642
661
  switch (_d.label) {
643
662
  case 0: return [4 /*yield*/, filter_consumer_bridge_to_sql_request_1.dbNamesOf(entity)];
@@ -656,15 +675,15 @@ var KnexSchemaBuilder = /** @class */ (function () {
656
675
  });
657
676
  }
658
677
  }
659
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
678
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
660
679
  finally {
661
680
  try {
662
681
  if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
663
682
  }
664
- finally { if (e_7) throw e_7.error; }
683
+ finally { if (e_8) throw e_8.error; }
665
684
  }
666
685
  return [4 /*yield*/, logSql(this.knex.schema.createTable(e.$entityName, function (b) {
667
- var e_8, _a;
686
+ var e_9, _a;
668
687
  try {
669
688
  for (var _b = tslib_1.__values(entity.fields), _c = _b.next(); !_c.done; _c = _b.next()) {
670
689
  var x = _c.value;
@@ -672,19 +691,19 @@ var KnexSchemaBuilder = /** @class */ (function () {
672
691
  if (remult3_1.isAutoIncrement(x))
673
692
  b.increments(cols_1.get(x).name);
674
693
  else {
675
- buildColumn(x, cols_1.get(x).name, b);
694
+ buildColumn(x, cols_1.get(x).name, b, supportsJson(_this.knex));
676
695
  if (x == entity.idMetadata.field)
677
696
  b.primary([cols_1.get(x).name]);
678
697
  }
679
698
  }
680
699
  }
681
700
  }
682
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
701
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
683
702
  finally {
684
703
  try {
685
704
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
686
705
  }
687
- finally { if (e_8) throw e_8.error; }
706
+ finally { if (e_9) throw e_9.error; }
688
707
  }
689
708
  }))];
690
709
  case 3:
@@ -698,6 +717,7 @@ var KnexSchemaBuilder = /** @class */ (function () {
698
717
  KnexSchemaBuilder.prototype.addColumnIfNotExist = function (entity, c) {
699
718
  return tslib_1.__awaiter(this, void 0, void 0, function () {
700
719
  var e, col, colName;
720
+ var _this = this;
701
721
  return tslib_1.__generator(this, function (_a) {
702
722
  switch (_a.label) {
703
723
  case 0: return [4 /*yield*/, filter_consumer_bridge_to_sql_request_1.dbNamesOf(entity)];
@@ -711,7 +731,7 @@ var KnexSchemaBuilder = /** @class */ (function () {
711
731
  case 2:
712
732
  if (!!(_a.sent())) return [3 /*break*/, 4];
713
733
  return [4 /*yield*/, logSql(this.knex.schema.alterTable(e.$entityName, function (b) {
714
- buildColumn(col, colName, b);
734
+ buildColumn(col, colName, b, supportsJson(_this.knex));
715
735
  }))];
716
736
  case 3:
717
737
  _a.sent();
@@ -723,8 +743,8 @@ var KnexSchemaBuilder = /** @class */ (function () {
723
743
  };
724
744
  KnexSchemaBuilder.prototype.verifyAllColumns = function (entity) {
725
745
  return tslib_1.__awaiter(this, void 0, void 0, function () {
726
- var e, _loop_2, this_2, _a, _b, col, e_9_1, err_3;
727
- var e_9, _c;
746
+ var e, _loop_2, this_2, _a, _b, col, e_10_1, err_3;
747
+ var e_10, _c;
728
748
  return tslib_1.__generator(this, function (_d) {
729
749
  switch (_d.label) {
730
750
  case 0: return [4 /*yield*/, filter_consumer_bridge_to_sql_request_1.dbNamesOf(entity)];
@@ -764,14 +784,14 @@ var KnexSchemaBuilder = /** @class */ (function () {
764
784
  return [3 /*break*/, 4];
765
785
  case 7: return [3 /*break*/, 10];
766
786
  case 8:
767
- e_9_1 = _d.sent();
768
- e_9 = { error: e_9_1 };
787
+ e_10_1 = _d.sent();
788
+ e_10 = { error: e_10_1 };
769
789
  return [3 /*break*/, 10];
770
790
  case 9:
771
791
  try {
772
792
  if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
773
793
  }
774
- finally { if (e_9) throw e_9.error; }
794
+ finally { if (e_10) throw e_10.error; }
775
795
  return [7 /*endfinally*/];
776
796
  case 10: return [3 /*break*/, 12];
777
797
  case 11:
@@ -788,7 +808,14 @@ var KnexSchemaBuilder = /** @class */ (function () {
788
808
  return KnexSchemaBuilder;
789
809
  }());
790
810
  exports.KnexSchemaBuilder = KnexSchemaBuilder;
791
- function buildColumn(x, dbName, b) {
811
+ function supportsJson(knex) {
812
+ var client = knex.client.config.client;
813
+ if ((client === null || client === void 0 ? void 0 : client.includes("sqlite3")) || (client === null || client === void 0 ? void 0 : client.includes("mssql")))
814
+ return false;
815
+ return true;
816
+ }
817
+ function buildColumn(x, dbName, b, supportsJson) {
818
+ if (supportsJson === void 0) { supportsJson = true; }
792
819
  if (x.valueType == Number) {
793
820
  if (!x.valueConverter.fieldTypeInDb) {
794
821
  var c = b.decimal(dbName);
@@ -828,6 +855,11 @@ function buildColumn(x, dbName, b) {
828
855
  c.defaultTo(0).notNullable();
829
856
  }
830
857
  }
858
+ else if (x.valueConverter.fieldTypeInDb == "json")
859
+ if (supportsJson)
860
+ b.json(dbName);
861
+ else
862
+ b.text(dbName);
831
863
  else
832
864
  b.specificType(dbName, x.valueConverter.fieldTypeInDb);
833
865
  }
@@ -273,9 +273,9 @@ var RestDataProviderHttpProviderUsingFetch = /** @class */ (function () {
273
273
  RestDataProviderHttpProviderUsingFetch.prototype.myFetch = function (url, options) {
274
274
  var e_5, _a;
275
275
  var _this = this;
276
- var headers = {
277
- "Content-type": "application/json"
278
- };
276
+ var headers = {};
277
+ if (options === null || options === void 0 ? void 0 : options.body)
278
+ headers["Content-type"] = "application/json";
279
279
  if (typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof (window.document.cookie !== 'undefined'))
280
280
  try {
281
281
  for (var _b = tslib_1.__values(window.document.cookie.split(';')), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -8,6 +8,7 @@ var filter_interfaces_1 = require("../filter/filter-interfaces");
8
8
  var sort_1 = require("../sort");
9
9
  var remult3_1 = require("../remult3");
10
10
  var remult_proxy_1 = require("../remult-proxy");
11
+ var valueConverters_1 = require("../valueConverters");
11
12
  // @dynamic
12
13
  var SqlDatabase = /** @class */ (function () {
13
14
  function SqlDatabase(sql) {
@@ -53,7 +54,26 @@ var SqlDatabase = /** @class */ (function () {
53
54
  });
54
55
  };
55
56
  SqlDatabase.prototype.getEntityDataProvider = function (entity) {
57
+ var e_1, _a;
56
58
  var _this = this;
59
+ if (!this.sql.supportsJsonColumnType) {
60
+ try {
61
+ for (var _b = tslib_1.__values(entity.fields.toArray()), _c = _b.next(); !_c.done; _c = _b.next()) {
62
+ var f = _c.value;
63
+ if (f.valueConverter.fieldTypeInDb === "json") {
64
+ //@ts-ignore
65
+ f.valueConverter = tslib_1.__assign(tslib_1.__assign({}, f.valueConverter), { toDb: valueConverters_1.ValueConverters.JsonString.toDb, fromDb: valueConverters_1.ValueConverters.JsonString.fromDb });
66
+ }
67
+ }
68
+ }
69
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
70
+ finally {
71
+ try {
72
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
73
+ }
74
+ finally { if (e_1) throw e_1.error; }
75
+ }
76
+ }
57
77
  return new ActualSQLServerDataProvider(entity, this, function (dbName) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
58
78
  return tslib_1.__generator(this, function (_a) {
59
79
  switch (_a.label) {
@@ -240,7 +260,7 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
240
260
  ActualSQLServerDataProvider.prototype.find = function (options) {
241
261
  return tslib_1.__awaiter(this, void 0, void 0, function () {
242
262
  var e, _a, colKeys, select, r, where, _b, first, segs, _loop_1, _c, _d, s, segs_1, segs_1_1, c, page;
243
- var e_1, _e, e_2, _f;
263
+ var e_2, _e, e_3, _f;
244
264
  var _this = this;
245
265
  return tslib_1.__generator(this, function (_g) {
246
266
  switch (_g.label) {
@@ -283,12 +303,12 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
283
303
  _loop_1(s);
284
304
  }
285
305
  }
286
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
306
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
287
307
  finally {
288
308
  try {
289
309
  if (_d && !_d.done && (_e = _c.return)) _e.call(_c);
290
310
  }
291
- finally { if (e_1) throw e_1.error; }
311
+ finally { if (e_2) throw e_2.error; }
292
312
  }
293
313
  try {
294
314
  for (segs_1 = tslib_1.__values(segs), segs_1_1 = segs_1.next(); !segs_1_1.done; segs_1_1 = segs_1.next()) {
@@ -304,12 +324,12 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
304
324
  select += ' desc';
305
325
  }
306
326
  }
307
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
327
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
308
328
  finally {
309
329
  try {
310
330
  if (segs_1_1 && !segs_1_1.done && (_f = segs_1.return)) _f.call(segs_1);
311
331
  }
312
- finally { if (e_2) throw e_2.error; }
332
+ finally { if (e_3) throw e_3.error; }
313
333
  }
314
334
  }
315
335
  if (options.limit) {
@@ -344,7 +364,7 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
344
364
  return result;
345
365
  };
346
366
  ActualSQLServerDataProvider.prototype.buildSelect = function (e) {
347
- var e_3, _a;
367
+ var e_4, _a;
348
368
  var select = '';
349
369
  var colKeys = [];
350
370
  try {
@@ -360,19 +380,19 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
360
380
  }
361
381
  }
362
382
  }
363
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
383
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
364
384
  finally {
365
385
  try {
366
386
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
367
387
  }
368
- finally { if (e_3) throw e_3.error; }
388
+ finally { if (e_4) throw e_4.error; }
369
389
  }
370
390
  return { colKeys: colKeys, select: select };
371
391
  };
372
392
  ActualSQLServerDataProvider.prototype.update = function (id, data) {
373
393
  return tslib_1.__awaiter(this, void 0, void 0, function () {
374
394
  var e, r, f, statement, added, _a, _b, x, v, _c, _d, colKeys, select;
375
- var e_4, _e;
395
+ var e_5, _e;
376
396
  var _this = this;
377
397
  return tslib_1.__generator(this, function (_f) {
378
398
  switch (_f.label) {
@@ -402,12 +422,12 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
402
422
  }
403
423
  }
404
424
  }
405
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
425
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
406
426
  finally {
407
427
  try {
408
428
  if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
409
429
  }
410
- finally { if (e_4) throw e_4.error; }
430
+ finally { if (e_5) throw e_5.error; }
411
431
  }
412
432
  _c = statement;
413
433
  return [4 /*yield*/, f.resolveWhere()];
@@ -446,7 +466,7 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
446
466
  ActualSQLServerDataProvider.prototype.insert = function (data) {
447
467
  return tslib_1.__awaiter(this, void 0, void 0, function () {
448
468
  var e, r, cols, vals, added, _a, _b, x, v, statement, _c, colKeys, select;
449
- var e_5, _d;
469
+ var e_6, _d;
450
470
  var _this = this;
451
471
  return tslib_1.__generator(this, function (_e) {
452
472
  switch (_e.label) {
@@ -476,12 +496,12 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
476
496
  }
477
497
  }
478
498
  }
479
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
499
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
480
500
  finally {
481
501
  try {
482
502
  if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
483
503
  }
484
- finally { if (e_5) throw e_5.error; }
504
+ finally { if (e_6) throw e_6.error; }
485
505
  }
486
506
  statement = "insert into " + e.$entityName + " (" + cols + ") values (" + vals + ")";
487
507
  _c = this.buildSelect(e), colKeys = _c.colKeys, select = _c.select;
package/src/entity.d.ts CHANGED
@@ -6,7 +6,11 @@ export interface EntityOptions<entityType = any> {
6
6
  caption?: string;
7
7
  /**
8
8
  * Determines if this Entity is available for get requests using Rest Api
9
- * @see [allowed](http://remult.dev/docs/allowed.html)*/
9
+ * @description
10
+ * Determines if one has any access to the data of an entity.
11
+ * @see [allowed](http://remult.dev/docs/allowed.html)
12
+ * @see to restrict data based on a criteria, use [apiPrefilter](https://remult.dev/docs/ref_entity.html#apiprefilter)
13
+ * */
10
14
  allowApiRead?: Allowed;
11
15
  /**
12
16
  * Determines if this entity can be updated through the api.
@@ -21,10 +25,15 @@ export interface EntityOptions<entityType = any> {
21
25
  /** sets the `allowApiUpdate`, `allowApiDelete` and `allowApiInsert` properties in a single set */
22
26
  allowApiCrud?: Allowed;
23
27
  /** A filter that determines which rows can be queries using the api.
28
+ * @description
29
+ * Use apiPrefilter in cases where you to restrict data based on user profile
24
30
  * @example
25
31
  * apiPrefilter: { archive:false }
26
32
  *
33
+ * @example
34
+ * apiPrefilter: ()=> remult.isAllowed("admin")?{}:{ archive:false }
27
35
  * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
36
+ *
28
37
  */
29
38
  apiPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
30
39
  /** A filter that will be used for all queries from this entity both from the API and from within the backend.
@@ -226,7 +226,11 @@ declare class EntityFullInfo<T> implements EntityMetadata<T> {
226
226
  }
227
227
  export declare function FieldType<valueType = any>(...options: (FieldOptions<any, valueType> | ((options: FieldOptions<any, valueType>, remult: Remult) => void))[]): (target: any) => any;
228
228
  export declare class Fields {
229
+ /**
230
+ * Stored as a JSON.stringify - to store as json use Fields.json
231
+ */
229
232
  static object<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
233
+ static json<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
230
234
  static dateOnly<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
231
235
  static date<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
232
236
  static integer<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
@@ -2539,6 +2539,9 @@ exports.FieldType = FieldType;
2539
2539
  var Fields = /** @class */ (function () {
2540
2540
  function Fields() {
2541
2541
  }
2542
+ /**
2543
+ * Stored as a JSON.stringify - to store as json use Fields.json
2544
+ */
2542
2545
  Fields.object = function () {
2543
2546
  var options = [];
2544
2547
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -2546,6 +2549,17 @@ var Fields = /** @class */ (function () {
2546
2549
  }
2547
2550
  return Field.apply(void 0, tslib_1.__spread([undefined], options));
2548
2551
  };
2552
+ Fields.json = function () {
2553
+ var options = [];
2554
+ for (var _i = 0; _i < arguments.length; _i++) {
2555
+ options[_i] = arguments[_i];
2556
+ }
2557
+ return Field.apply(void 0, tslib_1.__spread([undefined, {
2558
+ valueConverter: {
2559
+ fieldTypeInDb: "json"
2560
+ }
2561
+ }], options));
2562
+ };
2549
2563
  Fields.dateOnly = function () {
2550
2564
  var options = [];
2551
2565
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -1723,22 +1723,24 @@ db_tests_setup_1.testAll("test date", function (_a) {
1723
1723
  });
1724
1724
  }, false);
1725
1725
  db_tests_setup_1.testAll("test live query storage", function (_a) {
1726
- var db = _a.db, remult = _a.remult;
1726
+ var db = _a.db, remult = _a.remult, createEntity = _a.createEntity;
1727
1727
  return tslib_1.__awaiter(void 0, void 0, void 0, function () {
1728
1728
  var x, id, _b;
1729
1729
  return tslib_1.__generator(this, function (_c) {
1730
1730
  switch (_c.label) {
1731
- case 0:
1732
- x = new data_provider_live_query_storage_1.DataProviderLiveQueryStorage(db);
1733
- if (!db.ensureSchema) return [3 /*break*/, 2];
1734
- return [4 /*yield*/, x.ensureSchema()];
1731
+ case 0: return [4 /*yield*/, createEntity(data_provider_live_query_storage_1.LiveQueryStorageEntity)];
1735
1732
  case 1:
1736
1733
  _c.sent();
1737
- _c.label = 2;
1734
+ x = new data_provider_live_query_storage_1.DataProviderLiveQueryStorage(db);
1735
+ if (!db.ensureSchema) return [3 /*break*/, 3];
1736
+ return [4 /*yield*/, x.ensureSchema()];
1738
1737
  case 2:
1738
+ _c.sent();
1739
+ _c.label = 3;
1740
+ case 3:
1739
1741
  id = uuid_1.v4();
1740
1742
  return [4 /*yield*/, x.add({ id: id, entityKey: 'x', data: "noam" })];
1741
- case 3:
1743
+ case 4:
1742
1744
  _c.sent();
1743
1745
  return [4 /*yield*/, x.forEach("x", function (args) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
1744
1746
  return tslib_1.__generator(this, function (_a) {
@@ -1746,11 +1748,11 @@ db_tests_setup_1.testAll("test live query storage", function (_a) {
1746
1748
  return [2 /*return*/];
1747
1749
  });
1748
1750
  }); })];
1749
- case 4:
1751
+ case 5:
1750
1752
  _c.sent();
1751
1753
  _b = expect;
1752
1754
  return [4 /*yield*/, x.keepAliveAndReturnUnknownQueryIds([id])];
1753
- case 5:
1755
+ case 6:
1754
1756
  _b.apply(void 0, [(_c.sent())]).toEqual([]);
1755
1757
  return [2 /*return*/];
1756
1758
  }
@@ -1798,33 +1800,177 @@ db_tests_setup_1.testAll("test live query storage", function (x) { return tslib_
1798
1800
  var s, entityKey, id;
1799
1801
  return tslib_1.__generator(this, function (_a) {
1800
1802
  switch (_a.label) {
1801
- case 0:
1803
+ case 0: return [4 /*yield*/, x.createEntity(data_provider_live_query_storage_1.LiveQueryStorageEntity)];
1804
+ case 1:
1805
+ _a.sent();
1802
1806
  s = new data_provider_live_query_storage_1.DataProviderLiveQueryStorage(x.db);
1803
1807
  return [4 /*yield*/, s.ensureSchema()];
1804
- case 1:
1808
+ case 2:
1805
1809
  _a.sent();
1806
1810
  entityKey = "ek";
1807
1811
  id = 'id';
1808
1812
  return [4 /*yield*/, s.add({ id: id, entityKey: entityKey, data: {} })];
1809
- case 2:
1810
- _a.sent();
1811
- return [4 /*yield*/, s.add({ id: id, entityKey: entityKey, data: {} })];
1812
1813
  case 3:
1813
1814
  _a.sent();
1814
- x.remult.clearAllCache();
1815
1815
  return [4 /*yield*/, s.add({ id: id, entityKey: entityKey, data: {} })];
1816
1816
  case 4:
1817
1817
  _a.sent();
1818
- return [4 /*yield*/, s.keepAliveAndReturnUnknownQueryIds([id])];
1818
+ x.remult.clearAllCache();
1819
+ return [4 /*yield*/, s.add({ id: id, entityKey: entityKey, data: {} })];
1819
1820
  case 5:
1820
1821
  _a.sent();
1821
- return [4 /*yield*/, s.remove(id)];
1822
+ return [4 /*yield*/, s.keepAliveAndReturnUnknownQueryIds([id])];
1822
1823
  case 6:
1823
1824
  _a.sent();
1824
1825
  return [4 /*yield*/, s.remove(id)];
1825
1826
  case 7:
1827
+ _a.sent();
1828
+ return [4 /*yield*/, s.remove(id)];
1829
+ case 8:
1826
1830
  _a.sent();
1827
1831
  return [2 /*return*/];
1828
1832
  }
1829
1833
  });
1830
1834
  }); }, false, { exclude: [db_tests_setup_1.TestDbs.restDataProvider] });
1835
+ db_tests_setup_1.testAll("test json structure using object", function (_a) {
1836
+ var createEntity = _a.createEntity;
1837
+ return tslib_1.__awaiter(void 0, void 0, void 0, function () {
1838
+ var e, r, item;
1839
+ return tslib_1.__generator(this, function (_b) {
1840
+ switch (_b.label) {
1841
+ case 0:
1842
+ e = /** @class */ (function () {
1843
+ function class_6() {
1844
+ this.a = 0;
1845
+ }
1846
+ return class_6;
1847
+ }());
1848
+ DecoratorReplacer_1.describeClass(e, remult3_1.Entity("testJsonStructure", { allowApiCrud: true }), {
1849
+ a: remult3_1.Fields.number(),
1850
+ person: remult3_1.Fields.object()
1851
+ });
1852
+ return [4 /*yield*/, createEntity(e)];
1853
+ case 1:
1854
+ r = _b.sent();
1855
+ return [4 /*yield*/, r.insert({ a: 1, person: { firstName: "noam", lastName: "honig" } })];
1856
+ case 2:
1857
+ _b.sent();
1858
+ return [4 /*yield*/, r.findFirst()];
1859
+ case 3:
1860
+ item = _b.sent();
1861
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
1862
+ return [2 /*return*/];
1863
+ }
1864
+ });
1865
+ });
1866
+ }, false);
1867
+ var testObject = /** @class */ (function () {
1868
+ function testObject() {
1869
+ this.id = 0;
1870
+ this.person = { firstName: "noam", lastName: "honig" };
1871
+ }
1872
+ tslib_1.__decorate([
1873
+ remult3_1.Fields.integer(),
1874
+ tslib_1.__metadata("design:type", Object)
1875
+ ], testObject.prototype, "id", void 0);
1876
+ tslib_1.__decorate([
1877
+ remult3_1.Fields.object(),
1878
+ tslib_1.__metadata("design:type", Object)
1879
+ ], testObject.prototype, "person", void 0);
1880
+ testObject = tslib_1.__decorate([
1881
+ remult3_1.Entity("testObject", { allowApiCrud: true })
1882
+ ], testObject);
1883
+ return testObject;
1884
+ }());
1885
+ db_tests_setup_1.testAll("test object entity", function (_a) {
1886
+ var createEntity = _a.createEntity;
1887
+ return tslib_1.__awaiter(void 0, void 0, void 0, function () {
1888
+ var r, item;
1889
+ return tslib_1.__generator(this, function (_b) {
1890
+ switch (_b.label) {
1891
+ case 0: return [4 /*yield*/, createEntity(testObject)];
1892
+ case 1:
1893
+ r = _b.sent();
1894
+ return [4 /*yield*/, r.insert({ id: 1, person: { firstName: "noam", lastName: "honig" } })];
1895
+ case 2:
1896
+ _b.sent();
1897
+ return [4 /*yield*/, r.findFirst()];
1898
+ case 3:
1899
+ item = _b.sent();
1900
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
1901
+ return [2 /*return*/];
1902
+ }
1903
+ });
1904
+ });
1905
+ }, false);
1906
+ var testObjectJson = /** @class */ (function () {
1907
+ function testObjectJson() {
1908
+ this.id = 0;
1909
+ this.person = { firstName: "noam", lastName: "honig" };
1910
+ }
1911
+ tslib_1.__decorate([
1912
+ remult3_1.Fields.integer(),
1913
+ tslib_1.__metadata("design:type", Object)
1914
+ ], testObjectJson.prototype, "id", void 0);
1915
+ tslib_1.__decorate([
1916
+ remult3_1.Fields.json(),
1917
+ tslib_1.__metadata("design:type", Object)
1918
+ ], testObjectJson.prototype, "person", void 0);
1919
+ testObjectJson = tslib_1.__decorate([
1920
+ remult3_1.Entity("testObjectJson", { allowApiCrud: true })
1921
+ ], testObjectJson);
1922
+ return testObjectJson;
1923
+ }());
1924
+ db_tests_setup_1.testAll("test object entity", function (_a) {
1925
+ var createEntity = _a.createEntity;
1926
+ return tslib_1.__awaiter(void 0, void 0, void 0, function () {
1927
+ var r, item;
1928
+ return tslib_1.__generator(this, function (_b) {
1929
+ switch (_b.label) {
1930
+ case 0: return [4 /*yield*/, createEntity(testObjectJson)];
1931
+ case 1:
1932
+ r = _b.sent();
1933
+ return [4 /*yield*/, r.insert({ id: 1, person: { firstName: "noam", lastName: "honig" } })];
1934
+ case 2:
1935
+ _b.sent();
1936
+ return [4 /*yield*/, r.findFirst()];
1937
+ case 3:
1938
+ item = _b.sent();
1939
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
1940
+ return [2 /*return*/];
1941
+ }
1942
+ });
1943
+ });
1944
+ }, false);
1945
+ db_tests_setup_1.testAll("test json structure", function (_a) {
1946
+ var createEntity = _a.createEntity;
1947
+ return tslib_1.__awaiter(void 0, void 0, void 0, function () {
1948
+ var e, r, item;
1949
+ return tslib_1.__generator(this, function (_b) {
1950
+ switch (_b.label) {
1951
+ case 0:
1952
+ e = /** @class */ (function () {
1953
+ function class_7() {
1954
+ this.a = 0;
1955
+ }
1956
+ return class_7;
1957
+ }());
1958
+ DecoratorReplacer_1.describeClass(e, remult3_1.Entity("testJsonFieldType", { allowApiCrud: true }), {
1959
+ a: remult3_1.Fields.number(),
1960
+ person: remult3_1.Fields.json()
1961
+ });
1962
+ return [4 /*yield*/, createEntity(e)];
1963
+ case 1:
1964
+ r = _b.sent();
1965
+ return [4 /*yield*/, r.insert({ a: 1, person: { firstName: "noam", lastName: "honig" } })];
1966
+ case 2:
1967
+ _b.sent();
1968
+ return [4 /*yield*/, r.findFirst()];
1969
+ case 3:
1970
+ item = _b.sent();
1971
+ expect(item.person).toEqual({ firstName: "noam", lastName: "honig" });
1972
+ return [2 /*return*/];
1973
+ }
1974
+ });
1975
+ });
1976
+ }, false);
@@ -5,6 +5,7 @@ export interface SqlImplementation {
5
5
  transaction(action: (sql: SqlImplementation) => Promise<void>): Promise<void>;
6
6
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
7
7
  ensureSchema?(entities: EntityMetadata[]): Promise<void>;
8
+ supportsJsonColumnType?: boolean;
8
9
  }
9
10
  export interface SqlCommand extends SqlCommandWithParameters {
10
11
  execute(sql: string): Promise<SqlResult>;