diff --git a/packages/backend/src/om/definitions/PropType.js b/packages/backend/src/om/definitions/PropType.js index 40e9fa090d..94f9fed5d4 100644 --- a/packages/backend/src/om/definitions/PropType.js +++ b/packages/backend/src/om/definitions/PropType.js @@ -24,7 +24,7 @@ class PropType extends AdvancedBase { new WeakConstructorTrait(), ] - static create (context, data) { + static create (context, data, k) { const chains = {}; const super_type = data.from && (() => { const registry = context.get('registry'); @@ -51,7 +51,7 @@ class PropType extends AdvancedBase { } return new PropType({ - chains, + chains, name: k, }); } diff --git a/packages/backend/src/om/entitystorage/SQLES.js b/packages/backend/src/om/entitystorage/SQLES.js index 8a6cd1fe5b..b1584133b8 100644 --- a/packages/backend/src/om/entitystorage/SQLES.js +++ b/packages/backend/src/om/entitystorage/SQLES.js @@ -194,6 +194,29 @@ class SQLES extends BaseES { let value = data[col_name]; value = await prop.sql_dereference(value); + // TODO: This is not an ideal implementation, + // but this is only 6 lines of code so doing this + // "properly" is not sensible at this time. + // + // This is here because: + // - SQLES has access to the "db" object + // + // Writing this in `json`'s `sql_reference` method + // is also not ideal because that places the concern + // of supporting different database backends to + // property types. + // + // Best solution: SQLES has a SQLRefinements by + // composition. This SQLRefinements is applied + // to property types for the duration of this + // function. + if ( prop.typ.name === 'json' ) { + value = this.db.case({ + mysql: () => value, + otherwise: () => JSON.parse(value ?? '{}'), + })(); + } + entity_data[prop.name] = value; } const entity = await Entity.create({ om: this.om }, entity_data); @@ -286,6 +309,13 @@ class SQLES extends BaseES { } value = await prop.sql_reference(value); + + // TODO: This is done here for consistency; + // see the larger comment in sql_row_to_entity_ + // which does the reverse operation. + if ( prop.typ.name === 'json' ) { + value = JSON.stringify(value); + } if ( value && options.use_id ) { if ( value.hasOwnProperty('id') ) { diff --git a/packages/backend/src/om/mappings/app.js b/packages/backend/src/om/mappings/app.js index 4b50e43b7a..3a5663d58a 100644 --- a/packages/backend/src/om/mappings/app.js +++ b/packages/backend/src/om/mappings/app.js @@ -50,6 +50,9 @@ module.exports = { // so I've doubled that and rounded up maxlen: 7000, }, + metadata: { + type: 'json', + }, maximize_on_start: 'flag', background: 'flag', subdomain: { diff --git a/packages/backend/src/services/RegistrantService.js b/packages/backend/src/services/RegistrantService.js index d8bba0a41e..31ac6cf2b5 100644 --- a/packages/backend/src/services/RegistrantService.js +++ b/packages/backend/src/services/RegistrantService.js @@ -55,7 +55,7 @@ class RegistrantService extends BaseService { if ( data[k].from && ! seen.has(data[k].from) ) { throw new Error(`Super type "${data[k].from}" not found for property type "${k}"`); } - collection.set(k, PropType.create(ctx, data[k])); + collection.set(k, PropType.create(ctx, data[k], k)); seen.add(k); } } diff --git a/packages/backend/src/services/database/sqlite_setup/0012_appmetadata.sql b/packages/backend/src/services/database/sqlite_setup/0012_appmetadata.sql new file mode 100644 index 0000000000..4cada8c7e6 --- /dev/null +++ b/packages/backend/src/services/database/sqlite_setup/0012_appmetadata.sql @@ -0,0 +1 @@ +ALTER TABLE apps ADD COLUMN "metadata" JSON DEFAULT NULL;