Entity.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Puter.
  5. *
  6. * Puter is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. const { AdvancedBase } = require("@heyputer/putility");
  20. const { WeakConstructorFeature } = require("../../traits/WeakConstructorFeature");
  21. class Entity extends AdvancedBase {
  22. static FEATURES = [
  23. new WeakConstructorFeature(),
  24. ]
  25. constructor (args) {
  26. super(args);
  27. this.init_arg_keys_ = Object.keys(args);
  28. this.found = undefined;
  29. this.private_meta = {};
  30. this.values_ = {};
  31. }
  32. static async create (args, data) {
  33. const entity = new Entity(args);
  34. for ( const prop of Object.values(args.om.properties) ) {
  35. if ( ! data.hasOwnProperty(prop.name) ) continue;
  36. await entity.set(prop.name, data[prop.name]);
  37. }
  38. return entity;
  39. }
  40. async clone () {
  41. const args = {};
  42. for ( const k of this.init_arg_keys_ ) {
  43. args[k] = this[k];
  44. }
  45. const entity = new Entity(args);
  46. const BEHAVIOUR = 'A';
  47. if ( BEHAVIOUR === 'A' ) {
  48. entity.found = this.found;
  49. entity.private_meta = { ...this.private_meta };
  50. entity.values_ = { ...this.values_ };
  51. }
  52. if ( BEHAVIOUR === 'B' ) {
  53. for ( const prop of Object.values(this.om.properties) ) {
  54. if ( ! this.has(prop.name) ) continue;
  55. await entity.set(prop.name, await this.get(prop.name));
  56. }
  57. }
  58. return entity;
  59. }
  60. async apply (other) {
  61. for ( const prop of Object.values(this.om.properties) ) {
  62. if ( ! await other.has(prop.name) ) continue;
  63. await this.set(prop.name, await other.get(prop.name));
  64. }
  65. return this;
  66. }
  67. async set (key, value) {
  68. const prop = this.om.properties[key];
  69. if ( ! prop ) {
  70. throw Error(`property ${key} unrecognized`);
  71. }
  72. this.values_[key] = await prop.adapt(value);
  73. }
  74. async get (key) {
  75. const prop = this.om.properties[key];
  76. if ( ! prop ) {
  77. throw Error(`property ${key} unrecognized`);
  78. }
  79. let value = this.values_[key];
  80. let is_set = await prop.is_set(value);
  81. // If value is not set but we have a factory, use it.
  82. if ( ! is_set ) {
  83. value = await prop.factory();
  84. value = await prop.adapt(value);
  85. is_set = await prop.is_set(value);
  86. if ( is_set ) this.values_[key] = value;
  87. }
  88. // If value is not set but we have an implicator, use it.
  89. if ( ! is_set && prop.descriptor.imply ) {
  90. const { given, make } = prop.descriptor.imply;
  91. let imply_available = true;
  92. for ( const g of given ) {
  93. if ( ! await this.has(g) ) {
  94. imply_available = false;
  95. break;
  96. }
  97. }
  98. if ( imply_available ) {
  99. value = await make(this.values_);
  100. value = await prop.adapt(value);
  101. is_set = await prop.is_set(value);
  102. }
  103. if ( is_set ) this.values_[key] = value;
  104. }
  105. return value;
  106. }
  107. async del (key) {
  108. const prop = this.om.properties[key];
  109. if ( ! prop ) {
  110. throw Error(`property ${key} unrecognized`);
  111. }
  112. delete this.values_[key];
  113. }
  114. async has (key) {
  115. const prop = this.om.properties[key];
  116. if ( ! prop ) {
  117. throw Error(`property ${key} unrecognized`);
  118. }
  119. return await prop.is_set(await this.get(key));
  120. }
  121. async check (condition) {
  122. return await condition.check(this);
  123. }
  124. om_has_property (key) {
  125. return this.om.properties.hasOwnProperty(key);
  126. }
  127. // alias for `has`
  128. async is_set (key) {
  129. return await this.has(key);
  130. }
  131. async get_client_safe () {
  132. return await this.om.get_client_safe(this.values_);
  133. }
  134. }
  135. module.exports = {
  136. Entity,
  137. };