Source: recipes.ts

  1. /**
  2. * @author Michael Hasenstein <hasenstein@yahoo.com>
  3. * @copyright REFINIO GmbH 2018
  4. * @license CC-BY-NC-SA-2.5; portions MIT License
  5. * @version 0.0.1
  6. */
  7. /**
  8. * This module defines the core ONE object types. It has the type definitions as well as the
  9. * recipes.
  10. *
  11. * **The module deliberately does not import any other module.** This ensures that there are no
  12. * cyclic imports (type imports don't count, they don't exist at runtime).
  13. * @module
  14. */
  15. /**
  16. * A meta-type defined in `one.core/[src|lib]/@OneObjectInterfaces.d.ts` in module namespace
  17. * `"@OneObjectInterfaces"` that can be extended through TypeScript's
  18. * {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html|*declaration merging*} feature to include ONE object definitions defined through recipes of the application.
  19. *
  20. * In order to add your own project's unversioned ONE object types create similar .d.ts
  21. * file, declare a module namespace `@OneObjectInterfaces` and export an interface declaration for
  22. * `OneUnversionedObjectInterfaces` just as in the one.core file. If you tell `tsc`
  23. * (TypeScript server) via your `tsconfig.json` to include both one.core's and your own
  24. * definition files it will merge the declarations into one.
  25. *
  26. * To extend this structure have a look at file `one.core/@OneObjectInterfaces.d.ts` and do what
  27. * was one there to add ONE object types defined for the one.core tests for your own application
  28. * types.
  29. *
  30. * This interface contains the names (as keys) and TypeScript interface types (as values) of
  31. * all unversioned objects.
  32. *
  33. * **Important:** The string keys for each entry must be exactly the ONE object type name as
  34. * used in the "`name`" property of the recipe for that type.
  35. * @global
  36. * @typedef {object} OneUnversionedObjectInterfaces
  37. * @property {ONE-object-interface-type} type-name - Use the same string literal as used for
  38. * the "type" property in your ONE object(s) as key and the TypeScript interface definition
  39. * name as the value
  40. */
  41. declare module '@OneObjectInterfaces' {
  42. export interface OneUnversionedObjectInterfaces extends OneCrdtMetaObjectInterfaces {
  43. Keys: Keys;
  44. }
  45. }
  46. /**
  47. * ONE microdata object properties can store one of these types:
  48. *
  49. * - NumberValue
  50. * - BooleanValue
  51. * - StringifiableValue
  52. * - ReferenceToObjValue
  53. * - ReferenceToIdValue
  54. * - ReferenceToClobValue
  55. * - ReferenceToBlobValue
  56. * - MapValue
  57. * - BagValue
  58. * - ArrayValue
  59. * - SetValue
  60. * - ObjectValue;
  61. *
  62. * Conversion from and to the types is performed upon writing and reading ONE microdata objects:
  63. *
  64. * When reading microdata and creating a Javascript object representation of the ONE object
  65. * the strings will be converted to these types if the respective rule for the item has type
  66. * information. By default, everything remains a string.
  67. *
  68. * @global
  69. * @typedef {(
  70. * StringValue | IntegerValue | NumberValue | BooleanValue | StringifiableValue |
  71. * ReferenceToObjValue | ReferenceToIdValue | ReferenceToClobValue | ReferenceToBlobValue |
  72. * MapValue | BagValue | ArrayValue | SetValue | ObjectValue
  73. * )} ValueType
  74. */
  75. export type ValueType =
  76. | StringValue
  77. | IntegerValue
  78. | NumberValue
  79. | BooleanValue
  80. | StringifiableValue
  81. | ReferenceToObjValue
  82. | ReferenceToIdValue
  83. | ReferenceToClobValue
  84. | ReferenceToBlobValue
  85. | MapValue
  86. | BagValue
  87. | ArrayValue
  88. | SetValue
  89. | ObjectValue;
  90. /**
  91. * This object is part of {@link ValueType} and describes the value-type of a String.
  92. * @global
  93. * @typedef {object} StringValue
  94. * @property {'string'} type
  95. * @property {RegExp} [regexp]
  96. */
  97. export interface StringValue {
  98. type: 'string';
  99. regexp?: RegExp;
  100. }
  101. /**
  102. * This object is part of {@link ValueType} and describes the value-type of an Integer.
  103. * @global
  104. * @typedef {object} IntegerValue
  105. * @property {'integer'} type
  106. * @property {number} [max]
  107. * @property {number} [min]
  108. */
  109. export interface IntegerValue {
  110. type: 'integer';
  111. max?: number;
  112. min?: number;
  113. }
  114. /**
  115. * This object is part of {@link ValueType} and describes the value-type of a Number.
  116. * @global
  117. * @typedef {object} NumberValue
  118. * @property {'number'} type
  119. * @property {number} [max]
  120. * @property {number} [min]
  121. */
  122. export interface NumberValue {
  123. type: 'number';
  124. max?: number;
  125. min?: number;
  126. }
  127. /**
  128. * This object is part of {@link ValueType} and describes the value-type of a Boolean.
  129. * @global
  130. * @typedef {object} BooleanValue
  131. * @property {'boolean'} type
  132. */
  133. export interface BooleanValue {
  134. type: 'boolean';
  135. }
  136. /**
  137. * This object is part of {@link ValueType} and describes the value-type of a {@link SHA256Hash} of
  138. * an object.
  139. * @global
  140. * @typedef {object} ReferenceToObjValue
  141. * @property {'referenceToObj'} type
  142. * @property {Set<OneObjectTypeNames | '*'>} allowedTypes - Includes another recipe as a
  143. * sub-item. Create microdata span tag for complex data with attributes `itemscope` and
  144. * `itemtype="//refin.io/{THIS TYPE}"`. The actual values are placed in inner span tags
  145. * with an itemprop attributeSHA256IdHash. This is a list of acceptable types to include. The
  146. * itemprop` either is a hash link, or in imploded microdata those objects themselves are
  147. * included. If the list includes the type string '*' the meaning is "any type".
  148. */
  149. export interface ReferenceToObjValue {
  150. type: 'referenceToObj';
  151. allowedTypes: Set<OneObjectTypeNames | '*'>;
  152. }
  153. /**
  154. * This object is part of {@link ValueType} and describes the value-type of a {@link
  155. * SHA256IdHash} of an object.
  156. * @global
  157. * @typedef {object} ReferenceToIdValue
  158. * @property {'referenceToId'} type
  159. * @property {Set<OneVersionedObjectTypeNames | '*'>} allowedTypes - Same as `referenceToObj`
  160. * but the hash link points to an ID hash.
  161. */
  162. export interface ReferenceToIdValue {
  163. type: 'referenceToId';
  164. allowedTypes: Set<OneVersionedObjectTypeNames | '*'>;
  165. }
  166. /**
  167. * This object is part of {@link ValueType} and describes the value-type of a {@link SHA256Hash} of
  168. * a {@link CLOB}.
  169. * @global
  170. * @typedef {object} ReferenceToClobValue
  171. * @property {'referenceToClob'} type - Same as `referenceToObj` but the hash link points to a
  172. * CLOB (UTF-8) hash. It also is just a boolean value.
  173. */
  174. export interface ReferenceToClobValue {
  175. type: 'referenceToClob';
  176. }
  177. /**
  178. * This object is part of {@link ValueType} and describes the value-type of a {@link SHA256Hash} of
  179. * a {@link BLOB}.
  180. * @global
  181. * @typedef {object} ReferenceToBlobValue
  182. * @property {'referenceToBlob'} type - Same as `referenceToObj` but the hash link points to a
  183. * BLOB hash. It also is just a boolean value.
  184. */
  185. export interface ReferenceToBlobValue {
  186. type: 'referenceToBlob';
  187. }
  188. /**
  189. * This object is part of {@link ValueType} and describes the value-type of a Map Object.
  190. * @global
  191. * @typedef {object} MapValue
  192. * @property {'map'} type
  193. * @property {PrimitiveValueTypes|ReferenceValueTypes} key
  194. * @property {ValueType} value
  195. */
  196. export interface MapValue {
  197. type: 'map';
  198. key: PrimitiveValueTypes | ReferenceValueTypes;
  199. value: ValueType;
  200. }
  201. /**
  202. * This object is part of {@link ValueType} and describes the value-type of a Bag Object.
  203. * A "bag" is a data-structure that implements a multiset, which is a set
  204. * that allows multiple (duplicates). In the microdata the sequence of items is ordered by ONE.
  205. * @global
  206. * @typedef {object} BagValue
  207. * @property {'bag'} type
  208. * @property {ValueType} item
  209. */
  210. export interface BagValue {
  211. type: 'bag';
  212. item: ValueType;
  213. }
  214. /**
  215. * This object is part of {@link ValueType} and describes the value-type of an Array Object.
  216. * @global
  217. * @typedef {object} ArrayValue
  218. * @property {'array'} type
  219. * @property {ValueType} item
  220. */
  221. export interface ArrayValue {
  222. type: 'array';
  223. item: ValueType;
  224. }
  225. /**
  226. * This object is part of {@link ValueType} and describes the value-type of a Set Object.
  227. * @global
  228. * @typedef {object} SetValue
  229. * @property {'set'} type
  230. * @property {ValueType} item
  231. */
  232. export interface SetValue {
  233. type: 'set';
  234. item: ValueType;
  235. }
  236. /**
  237. * This object is part of {@link ValueType} and describes the value-type of an ONE Object.
  238. * @global
  239. * @typedef {object} ObjectValue
  240. * @property {'object'} type
  241. * @property {RecipeRule[]} rules
  242. */
  243. export interface ObjectValue {
  244. type: 'object';
  245. rules: RecipeRule[];
  246. }
  247. /**
  248. * @global
  249. * @typedef {object} StringifiableValue
  250. * @property {'stringifiable'} type
  251. */
  252. export interface StringifiableValue {
  253. type: 'stringifiable';
  254. }
  255. /**
  256. * @global
  257. * @typedef {(
  258. * StringValue | IntegerValue | NumberValue | BooleanValue | StringifiableValue
  259. * )} PrimitiveValueTypes
  260. */
  261. export type PrimitiveValueTypes =
  262. | StringValue
  263. | IntegerValue
  264. | NumberValue
  265. | BooleanValue
  266. | StringifiableValue;
  267. /**
  268. * @global
  269. * @typedef {(
  270. * ReferenceToObjValue | ReferenceToIdValue | ReferenceToClobValue | ReferenceToBlobValue
  271. * )} PrimitiveValueTypes
  272. */
  273. export type ReferenceValueTypes =
  274. | ReferenceToObjValue
  275. | ReferenceToIdValue
  276. | ReferenceToClobValue
  277. | ReferenceToBlobValue;
  278. /**
  279. * A meta-type defined in `one.core/@OneObjectInterfaces.d.ts` in module namespace
  280. * `"@OneObjectInterfaces"` that can be extended through TypeScript's
  281. * {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html|*declaration merging*} feature to include ONE object definitions defined through recipes of the application.
  282. *
  283. * In order to add your own project's ID ONE object types create similar .d.ts file,
  284. * declare a module namespace `@OneObjectInterfaces` and export an interface declaration for
  285. * `OneIdObjectInterfaces` just as in the one.core file. If you tell `tsc` (TypeScript
  286. * server) via your `tsconfig.json` to include both one.core's and your own definition files
  287. * it will merge the declarations into one.
  288. *
  289. * This interface contains the names (as keys) and TypeScript interface types (as values) of
  290. * all ID objects. Unless you need to refer to the ID object types by name it probably is
  291. * best to use TypeScript's built-in `Pick<T, K>` helper to pick the ID object properties
  292. * from the full versioned object types. Usually only the latter will have named interfaces.
  293. * If necessary, in .ts code files you can always refer to ID object interfaces using
  294. * `OneIdObjectInterfaces[TypeId]`, where `TypeId` is the appropriate string key. For key
  295. * names one.core follows the rule to take the name of the versioned object type and append, for
  296. * example, 'Id'.
  297. *
  298. * **Note** that ID object interfaces are special and must be used explicitly, they are not
  299. * part in any of the unions or merged definitions of ONE object types.
  300. * Except for in rare places ID object types are not to be permitted even when the
  301. * respective versioned object types are, because the ID object types may miss properties
  302. * that are not ID properties but still non-optional. ID objects are only used to calculate
  303. * ID hashes and never written, nor should they be used for processing.
  304. *
  305. * That is why the name (key) you choose for the ID object type may be arbitrary, it is not
  306. * used as type name. Only the values are used, i.e. the ID object declarations.
  307. *
  308. * This key/value interface still is necessary, the declarations cannot just be written
  309. * directly to `OneIdObjectTypes`: Declaration merging of ID object types declared for the
  310. * application requires this key/value structure.
  311. * @global
  312. * @typedef {object} OneIdObjectInterfaces
  313. * @property {ONE-object-interface-type} type-name - Use the same string literal as used for
  314. * the "$type$" property in your ONE object(s) as key and the TypeScript interface definition
  315. * name as the value
  316. */
  317. declare module '@OneObjectInterfaces' {
  318. // eslint-disable-next-line no-undef -- OneCrdtIdObjectInterfaces *is* defined
  319. export interface OneIdObjectInterfaces extends OneCrdtIdObjectInterfaces {
  320. Access: Pick<Access, '$type$' | 'object'>;
  321. Chum: Pick<Chum, '$type$' | 'name' | 'instance' | 'person'>;
  322. Group: Pick<Group, '$type$' | 'name'>;
  323. IdAccess: Pick<IdAccess, '$type$' | 'id'>;
  324. Instance: Pick<Instance, '$type$' | 'name' | 'owner'>;
  325. Module: Pick<Module, '$type$' | 'name'>;
  326. Person: PersonId;
  327. Recipe: Pick<Recipe, '$type$' | 'name'>;
  328. MetaObjectList: Pick<MetaObjectList, 'object' | '$type$'>;
  329. }
  330. }
  331. /**
  332. * A meta-type defined in `one.core/@OneObjectInterfaces.d.ts` in module namespace
  333. * `"@OneObjectInterfaces"` that can be extended through TypeScript's
  334. * {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html|*declaration merging*} feature to include ONE object definitions defined through recipes of the application.
  335. *
  336. * In order to add your own project's versioned ONE object types create similar .d.ts
  337. * file, declare a module namespace `@OneObjectInterfaces` and export an interface declaration for
  338. * `OneVersionedObjectInterfaces` just as in the one.core file. If you tell `tsc`
  339. * (TypeScript server) via your `tsconfig.json` to include both one.core's and your own
  340. * definition files it will merge the declarations into one.
  341. *
  342. * This interface contains the names (as keys) and TypeScript interface types (as values) of
  343. * all versioned objects.
  344. *
  345. * **Important:** The string keys for each entry must be exactly the ONE object type name as
  346. * used in the "`name`" property of the recipe for that type.
  347. * @global
  348. * @typedef {object} OneVersionedObjectInterfaces
  349. * @property {ONE-object-interface-type} type-name - Use the same string literal as used for
  350. * the "$type$" property in your ONE object(s) as key and the TypeScript interface definition
  351. * name as the value
  352. */
  353. declare module '@OneObjectInterfaces' {
  354. export interface OneVersionedObjectInterfaces extends OneCrdtObjectInterfaces {
  355. Access: Access;
  356. Chum: Chum;
  357. Group: Group;
  358. IdAccess: IdAccess;
  359. Instance: Instance;
  360. Module: Module;
  361. Person: Person;
  362. Recipe: Recipe;
  363. MetaObjectList: MetaObjectList;
  364. }
  365. }
  366. /**
  367. * Defined in one.core's `@OneObjectInterfaces.d.ts` file, this is the result of merging the
  368. * declarations of {@link OneUnversionedObjectInterfaces}, {@link OneVersionedObjectInterfaces}.
  369. *
  370. * This is a key/value map object where the keys are *all* valid ONE object type names, and the
  371. * values are the interface type (i.e. ONE object) definitions.
  372. *
  373. * ID object interface definitions are not included in this map because except for in rare
  374. * places ID object types are not to be permitted even when the respective versioned object
  375. * types are, because the ID object types may miss properties that are not ID properties but
  376. * still non-optional. ID objects are only used to calculate ID hashes and never written,
  377. * nor should they be used for processing.
  378. * @global
  379. * @typedef {object} OneObjectInterfaces
  380. */
  381. export type OneObjectInterfaces = OneUnversionedObjectInterfaces & OneVersionedObjectInterfaces;
  382. /**
  383. * This union is obtained by extracting all keys from {@link OneUnversionedObjectInterfaces}.
  384. * @global
  385. * @typedef {"Keys" | AllYourUnversionedTypeNames} OneUnversionedObjectTypeNames
  386. */
  387. export type OneUnversionedObjectTypeNames = keyof OneUnversionedObjectInterfaces;
  388. /**
  389. * This union is obtained by extracting all values from {@link OneUnversionedObjectInterfaces}.
  390. * @global
  391. * @typedef {Keys | AllYourUnversionedTypes} OneUnversionedObjectTypes
  392. */
  393. export type OneUnversionedObjectTypes =
  394. OneUnversionedObjectInterfaces[keyof OneUnversionedObjectInterfaces];
  395. /**
  396. * This union is obtained by extracting all keys from {@link OneVersionedObjectInterfaces}.
  397. * @global
  398. * @typedef {
  399. * "Access" | "Chum" | "Group" | "Instance" | "Module" | "Person" | "Recipe" |
  400. * AllYourVersionedTypeNames
  401. * } OneVersionedObjectTypeNames
  402. */
  403. export type OneVersionedObjectTypeNames = keyof OneVersionedObjectInterfaces;
  404. /**
  405. * This union is obtained by extracting all values from {@link OneVersionedObjectInterfaces}.
  406. * @global
  407. * @typedef {
  408. * Access | Chum | Group | IdAccess | Instance | Module | Person | Recipe |
  409. * AllYourVersionedTypes
  410. * } OneVersionedObjectTypes
  411. */
  412. export type OneVersionedObjectTypes =
  413. OneVersionedObjectInterfaces[keyof OneVersionedObjectInterfaces];
  414. /**
  415. * This union is obtained by extracting all values from {@link OneIdObjectInterfaces}.
  416. * @global
  417. * @typedef {
  418. * AccessId | ChumId | GroupId | InstanceId | ModuleId | PersonId | RecipeId |
  419. * AllYourIdObjectTypes
  420. * } OneIdObjectTypes
  421. */
  422. export type OneIdObjectTypes = OneIdObjectInterfaces[keyof OneIdObjectInterfaces];
  423. /**
  424. * The union of all "`name`" property values of all {@link Recipe}s used by one.core and the
  425. * application. The type is created as union of {@link OneUnversionedObjectTypeNames} and
  426. * {@link OneVersionedObjectTypeNames}.
  427. * @global
  428. * @typedef {OneUnversionedObjectTypeNames|OneVersionedObjectTypeNames} OneObjectTypeNames
  429. */
  430. export type OneObjectTypeNames = OneUnversionedObjectTypeNames | OneVersionedObjectTypeNames;
  431. /**
  432. * The union of all interfaces of ONE object types used by one.core and the application. The
  433. * type is created as union of {@link OneUnversionedObjectTypes} and
  434. * {@link OneVersionedObjectTypes}.
  435. * @global
  436. * @typedef {OneUnversionedObjectTypes | OneVersionedObjectTypes} OneObjectTypes
  437. */
  438. export type OneObjectTypes = OneUnversionedObjectTypes | OneVersionedObjectTypes;
  439. /**
  440. * The ID object of a Person with only "email" as the sole ID property of {@link Person}
  441. * objects.
  442. * @typedef {object} PersonId
  443. * @property {'Person'} $type$
  444. * @property {string} email
  445. */
  446. export type PersonId = Pick<Person, '$type$' | 'email'>;
  447. /**
  448. * This is a *virtual type* representing BLOB files. It is used as a generic parameter type
  449. * for {@link SHA256Hash} and {@link SHA256IdHash}.
  450. * @global
  451. * @typedef {object} BLOB
  452. */
  453. export interface BLOB {
  454. _: 'BLOB';
  455. }
  456. /**
  457. * This is a *virtual type* representing CLOB (UTF-8 text) files. It is used as a generic
  458. * parameter type for {@link SHA256Hash} and {@link SHA256IdHash}.
  459. * @global
  460. * @typedef {object} CLOB
  461. */
  462. export interface CLOB {
  463. _: 'CLOB';
  464. }
  465. /**
  466. * The union of all "`name`" property values of all {@link Recipe}s used by one.core and the
  467. * application plus 'BLOB' for binary objects and 'CLOB' for UTF-8 objects.
  468. * @global
  469. * @typedef {OneObjectTypeNames|BLOB|CLOB} HashTypes
  470. */
  471. export type HashTypes = OneObjectTypes | BLOB | CLOB;
  472. /**
  473. * There are two Access objects that are identical in structure and purpose except for in name:
  474. * 'Access' points to immutable graphs.
  475. *
  476. * ### Example
  477. *
  478. * Javascript representation:
  479. *
  480. * ```javascript
  481. * const obj = {
  482. * $type$: 'Access',
  483. * object: hash,
  484. * person: [personIdHash]
  485. * };
  486. * ```
  487. *
  488. * HTML microdata representation:
  489. *
  490. * ```html
  491. * <div itemscope itemtype="//refin.io/Access">
  492. * <a itemprop="object" href="${hash}">${hash}</a>
  493. * <a itemprop="person" href="${personIdHash}">${personIdHash}</a>
  494. * </span>
  495. * ```
  496. * @global
  497. * @typedef {object} Access
  498. * @property {'Access'} type Fixed string 'Access'
  499. * @property {SHA256Hash} object A versioned or unversioned object link to a concrete
  500. * versioned or unversioned object that the access rights are being set for.
  501. * @property {SHA256IdHash[]} [person] An array of ID references to Person objects.
  502. * @property {SHA256IdHash[]} [group] An array of ID references to Group objects. *Only
  503. * the latest version* of a group is granted access!
  504. */
  505. export interface Access {
  506. $type$: 'Access';
  507. object: SHA256Hash;
  508. person: Array<SHA256IdHash<Person>>;
  509. group: Array<SHA256IdHash<Group>>;
  510. }
  511. /**
  512. * Same as {@link Access|Access object} but instead of a reference to a concrete object it
  513. * has a reference to an ID object of a versioned object and grants access to all current *and
  514. * future* versions of the object.
  515. * @global
  516. * @typedef {object} IdAccess
  517. * @property {'IdAccess'} $type$ Fixed string 'IdAccess' (which is mutable, since the ID
  518. * reference also points to any future versions of the object) depending on if the directed
  519. * graph of ONE objects it points to an ID object.
  520. * @property {SHA256IdHash} id A reference to all versions of an ID object that the access
  521. * rights are being set for.
  522. * @property {SHA256IdHash[]} [person] An array of ID references to Person objects.
  523. * @property {SHA256IdHash[]} [group] An array of ID references to Group objects. *Only
  524. * the latest version* of a group is granted access!
  525. */
  526. export interface IdAccess {
  527. $type$: 'IdAccess';
  528. id: SHA256IdHash;
  529. person: Array<SHA256IdHash<Person>>;
  530. group: Array<SHA256IdHash<Group>>;
  531. }
  532. /**
  533. * This type is included in {@link Chum} objects as well as used internally.
  534. * The numbers are without network overhead. The number of sent requests always includes the
  535. * connect request, so after communication finished both parties will have sent one more request
  536. * than they themselves received, since the connect request is to the communication server!
  537. * @global
  538. * @typedef {object} WebsocketStatistics
  539. * @property {number} requestsSentTotal Total number of requests made thus far
  540. * @property {number} requestsReceivedTotal Total number of requests received thus far
  541. * @property {number} requestsReceivedInvalid Total number of requests received that had to be
  542. * ignored because they were either unparsable (invalid JSON) or otherwise unusable
  543. */
  544. export interface WebsocketStatistics {
  545. requestsSentTotal: number;
  546. requestsReceivedTotal: number;
  547. requestsReceivedInvalid: number;
  548. }
  549. /**
  550. * A Chum object defines a filter for exchanging data with other instances.
  551. * Initially it only filters by persons.
  552. *
  553. * ### Example
  554. *
  555. * ```html
  556. * <div itemscope itemtype="//refin.io/Chum">
  557. * <span itemprop="name">ThisChumsName</span>
  558. * <span itemprop="instance">${name1}</span>
  559. * <span itemprop="instance">${name2}</span>
  560. * <span itemprop="person">${hash1}</span>
  561. * <span itemprop="person">${hash2}</span>
  562. * <span itemprop="highestRemoteTimestamp">${timestamp1}</span>
  563. * ...
  564. * </span>
  565. * ```
  566. * @global
  567. * @typedef {object} Chum
  568. * @property {'Chum'} $type$ - Fixed string 'Chum'
  569. * @property {string} name
  570. * @property {string[]} instance - A pair of instance names
  571. * @property {SHA256IdHash[]} person - A pair of Person ID hashes. The first one is the one the
  572. * local instance (owner of the Chum object) used for authentication to the remote instance,
  573. * the second one is the one the remote instance used to do the same for the local instance.
  574. * @property {number} highestRemoteTimestamp - A numeric timestamp specifying a date-time on
  575. * the remote system. We can be sure to have all objects accessible to us created or made
  576. * accessible to us before that time. NOTE: If older objects are made accessible it
  577. * will be through an object created at a later time. Since this cutoff date-time specifies
  578. * the root node of an accessible directed graph, which by necessity (hash links!) has to be
  579. * created after all others, we get older objects linked from such a root node in any case.
  580. * This timestamp is only used to filter root nodes.
  581. * @property {Array<SHA256Hash>} AtoBObjects - Record of all transfers from A to B
  582. * @property {Array<SHA256IdHash>} AtoBIdObjects - Record of all ID transfers from A to B
  583. * @property {Array<SHA256Hash>} AtoBBlob - Record of all BLOB transfers from A to B
  584. * @property {Array<SHA256Hash>} AtoBClob - Record of all CLOB transfers from A to B
  585. * @property {Array<SHA256Hash>} BtoAObjects - Record of all transfers from B to A
  586. * @property {Array<SHA256IdHash>} BtoAIdObjects - Record of all ID transfers from B to A
  587. * @property {Array<SHA256Hash>} BtoABlob - Record of all BLOB transfers from B to A
  588. * @property {Array<SHA256Hash>} BtoAClob - Record of all CLOB transfers from B to A
  589. * @property {number} BtoAExists - How many hashes we already had and did not need to import
  590. * @property {Error[]} errors - Record of exceptions encountered while running
  591. * @property {Set<SHA256Hash>} [unacknowledged] - List of hashes of files sent for which we did
  592. * not receive an acknowledgement that it was successfully stored by the importer.
  593. * **NOTE:** These hashes don't cause any reverse map entries to be created - this field is
  594. * somewhat optional and "FYI". The main fields are the other transfers-recording fields.
  595. * @property {WebsocketStatistics} [statistics] - Data about the exchange such as bytes
  596. * sent/received
  597. */
  598. export interface Chum {
  599. $type$: 'Chum';
  600. name: string;
  601. instance: [string, string];
  602. person: [SHA256IdHash<Person>, undefined | SHA256IdHash<Person>];
  603. highestRemoteTimestamp: number;
  604. AtoBObjects: SHA256Hash[];
  605. AtoBIdObjects: SHA256IdHash[];
  606. AtoBBlob: Array<SHA256Hash<BLOB>>;
  607. AtoBClob: Array<SHA256Hash<CLOB>>;
  608. BtoAObjects: SHA256Hash[];
  609. BtoAIdObjects: SHA256IdHash[];
  610. BtoABlob: Array<SHA256Hash<BLOB>>;
  611. BtoAClob: Array<SHA256Hash<CLOB>>;
  612. BtoAExists: number;
  613. errors: Error[];
  614. unacknowledged?: Set<SHA256Hash<HashTypes> | SHA256IdHash>;
  615. statistics?: WebsocketStatistics;
  616. }
  617. /**
  618. * {@link Access|Access} objects link to `Group` objects to grant access rights.
  619. *
  620. * ### Example
  621. *
  622. * Javascript representation:
  623. *
  624. * ```javascript
  625. * const obj = {
  626. * $type$: 'Group',
  627. * name: name,
  628. * person: [Person1-idHash, Person2-idHash]
  629. * };
  630. * ```
  631. *
  632. * HTML microdata representation:
  633. *
  634. * ```html
  635. * <span itemprop="item" itemscope itemtype="//refin.io/Group">
  636. * <span itemprop="name">${name}</span>
  637. * <span itemprop="person">${Person1-ID-hash}</span>
  638. * <span itemprop="person">${Person2-ID-hash}</span>
  639. * </span>
  640. * ```
  641. * @global
  642. * @typedef {object} Group
  643. * @property {'Group'} $type$ - Fixed string 'Group'
  644. * @property {string} name
  645. * @property {SHA256IdHash[]} person
  646. *
  647. */
  648. export interface Group {
  649. $type$: 'Group';
  650. name: string;
  651. person: Array<SHA256IdHash<Person>>;
  652. }
  653. /**
  654. * An Instance object describes one instance of the app. Multiple instances can co-exist on
  655. * one, and even in the same disk space. Both instances would share the same directory and
  656. * much of their respective data.
  657. *
  658. * The encryption key pair is generated by TweetNaCl.js and is stored in two Base 64 encoded
  659. * strings:
  660. * - Base 64 character set: {@link https://tools.ietf.org/html/rfc4648#section-4}
  661. * - Base 64 length: {@link https://stackoverflow.com/q/13378815/544779}
  662. * - TweetNaCl length is n=32 bytes
  663. * - Base 64 encoded length: Math.ceil(4 * n/3) => 43, plus trailing "=" padding character
  664. * for a total length of 44 characters.
  665. *
  666. * ### Example
  667. *
  668. * Javascript representation:
  669. *
  670. * ```javascript
  671. * const obj = {
  672. * $type$: 'Instance',
  673. * name: 'InstanceName',
  674. * owner: personIdHash,
  675. * publicKey: blobHash,
  676. * secretKey: blobHash,
  677. * module: [moduleHash]
  678. * };
  679. * ```
  680. *
  681. * HTML microdata representation:
  682. *
  683. * ```html
  684. * <div itemscope itemtype="//refin.io/Instance">
  685. * <div itemscope="name">InstanceName</span>
  686. * <span itemprop="owner">${personIdHash}</span>
  687. * <span itemprop="publicKey">${publicKey}</span>
  688. * <a itemprop="module" href="${moduleHash}">${module1-hash}</a>
  689. * </span>
  690. * ```
  691. * @global
  692. * @typedef {object} Instance
  693. * @property {'Instance'} $type$
  694. * @property {string} name - The name of the instance chosen by the user
  695. * @property {SHA256IdHash} owner - A reference to a Person ID object
  696. * @property {SHA256Hash[]} recipe - A list of ONE object recipes
  697. * @property {SHA256Hash[]} module - A list of code modules
  698. * @property {Map<OneObjectTypeNames,null|Set<string>>} enabledReverseMapTypes - A Map
  699. * object with ONE object type names as keys and an array of "itemprop" properties from the
  700. * recipe for that particular ONE object type for which reverse maps should be written. For
  701. * all other types and/or properties not mentioned in this Map reverse map entries are not
  702. * created.
  703. * @property {Map<OneObjectTypeNamesForIdObjects,null|Set<string>>}
  704. * enabledReverseMapTypesForIdObjects - A Map object with ONE object type names as keys and an
  705. * array of "itemprop" properties from the recipe for that particular ONE object type for which
  706. * ID object reverse maps should be written. For all other types and/or properties not
  707. * mentioned in this Map reverse map entries are not created.
  708. */
  709. export interface Instance {
  710. $type$: 'Instance';
  711. name: string;
  712. owner: SHA256IdHash<Person>;
  713. recipe: Array<SHA256Hash<Recipe>>;
  714. module: Array<SHA256Hash<Module>>;
  715. enabledReverseMapTypes: Map<OneObjectTypeNames, Set<string>>;
  716. enabledReverseMapTypesForIdObjects: Map<OneVersionedObjectTypeNames, Set<string>>;
  717. }
  718. /**
  719. * This object stores the *public* encryption and sign keys for a given {@link Instance} or
  720. * {@link Person} ID. The secret keys are stored in a special non-shared private storage area.
  721. * @global
  722. * @typedef {object} Keys
  723. * @property {'Keys'} $type$
  724. * @property {SHA256IdHash} owner
  725. * @property {HexString} publicKey
  726. * @property {HexString} publicSignKey
  727. */
  728. export interface Keys {
  729. $type$: 'Keys';
  730. owner: SHA256IdHash<Instance | Person>;
  731. publicKey: HexString;
  732. publicSignKey: HexString;
  733. }
  734. /**
  735. * ### Example
  736. *
  737. * Javascript representation:
  738. *
  739. * ```javascript
  740. * const obj = {
  741. * $type$: 'Module',
  742. * name: '@module/imap-mailbox-handler',
  743. * version: '1.0',
  744. * requires: [
  745. * '@module/imap-promisifier.js',
  746. * '@one/message-bus.js',
  747. * '@one/storage.js'
  748. * ],
  749. * code: clobHash
  750. * };
  751. * ```
  752. *
  753. * HTML microdata representation:
  754. *
  755. * ```html
  756. * <div itemscope itemtype="//refin.io/Module">
  757. * <span itemprop="name">@module/imap-mailbox-handler</span>
  758. * <span itemprop="version">1.0</span>
  759. * <span itemprop="requires">@module/imap-promisifier.js</span>
  760. * <span itemprop="requires">lib/message-bus.js</span>
  761. * <span itemprop="requires">lib/storage.js</span>
  762. * <span itemprop="code">${CLOB-hash}</span>
  763. * </span>
  764. * ```
  765. * @global
  766. * @typedef {object} Module
  767. * @property {'Module'} $type$
  768. * @property {string} name The name that will be used by other modules to request this module
  769. * @property {string[]} [provides]
  770. * @property {string[]} [requires] The modules called from this module, extracted from
  771. * require() or import calls from its code
  772. * @property {string} [version] An optional version string
  773. * @property {SHA256Hash} [code] Link to a UTF-8 CLOB with the Javascript code for this module
  774. */
  775. export interface Module {
  776. $type$: 'Module';
  777. name: string;
  778. provides?: string[];
  779. requires?: string[];
  780. version?: string;
  781. code?: SHA256Hash<CLOB>;
  782. }
  783. /**
  784. * ### Example
  785. *
  786. * Javascript representation:
  787. *
  788. * ```javascript
  789. * const obj = {
  790. * $type$: 'Person',
  791. * email: 'members@gmx.net',
  792. * name: 'Foo Test'
  793. * };
  794. * ```
  795. *
  796. * HTML microdata representation:
  797. *
  798. * ```html
  799. * <div itemscope itemtype="//refin.io/Person">
  800. * <span itemprop="email">members@gmx.net</span>
  801. * </span>
  802. * ```
  803. * @global
  804. * @typedef {object} Person
  805. * @property {'Person'} $type$
  806. * @property {string} email - A person-identifying unique email address
  807. * @property {string} [name]
  808. */
  809. export interface Person {
  810. $type$: 'Person';
  811. email: string;
  812. name?: string;
  813. }
  814. /**
  815. * The array of rules determines the properties of the ONE object and their order (in the
  816. * written microdata representation).
  817. *
  818. * ### Example
  819. *
  820. * Javascript representation:
  821. *
  822. * ```javascript
  823. * const obj = {
  824. * $type$: 'Recipe',
  825. * name: ONE-object-type-name,
  826. * version: 1,
  827. * rule: [
  828. * {
  829. * itemprop: property1-name
  830. * isId: true
  831. * valueType: 'number'
  832. * },
  833. * {
  834. * itemprop: property2-name,
  835. * regexp: /^[\w]*+$/
  836. * },
  837. * {
  838. * itemprop: property3-name
  839. * valueType: 'map'
  840. * },
  841. * {
  842. * itemprop: property4-name
  843. * referenceToObj: new Set(['*'])
  844. * }
  845. * ]
  846. * };
  847. * ```
  848. *
  849. * HTML microdata representation:
  850. *
  851. * ```html
  852. * <div itemscope itemtype="//refin.io/Recipe">
  853. * <span itemprop="name">${ONE-object-type-name}</span>
  854. * <span itemprop="rule">
  855. * <span itemprop="itemprop">${property1-name}</span>
  856. * <span itemprop="isId">true</span>
  857. * <span itemprop="valueType">number</span>
  858. * </span>
  859. * <span itemprop="rule">
  860. * <span itemprop="itemprop">${property2-name}</span>
  861. * </span>
  862. * <span itemprop="rule">
  863. * <span itemprop="itemprop">${property3-name}</span>
  864. * <span itemprop="valueType">Map</span>
  865. * </span>
  866. * <span itemprop="rule">
  867. * <span itemprop="itemprop">${property4-name}</span>
  868. * <span itemprop="referenceToObj">['*']</span>
  869. * </span>
  870. * </span>
  871. * ```
  872. * @global
  873. * @typedef {object} Recipe
  874. * @property {'Recipe'} $type$
  875. * easily load a specific version of this versioned Recipe object.
  876. * @property {string} name The type-string constant identifying this ONE object type
  877. * @property {RecipeRule[]} rule Array of rules
  878. */
  879. export interface Recipe {
  880. $type$: 'Recipe';
  881. name: OneObjectTypeNames;
  882. rule: RecipeRule[];
  883. crdtConfig?: Map<string, CRDTImplementationNames>;
  884. }
  885. /**
  886. * Important note (from @sebastian). I decided to keep exclude 'list' even if we don't have
  887. * the list field anymore in {@link RecipeRule}. It will remove 'array','bag' or 'set' field in
  888. * the {@link RecipeRule.itemtype} and keep only the item type.
  889. *
  890. *
  891. * The recipe-rule property "inheritFrom" can be either a string (common inheritance) or an
  892. * object (inheritance with additional options). This is the type of the object in the latter case.
  893. * @global
  894. * @typedef {object} RuleInheritanceWithOptions
  895. * @property {string} rule - The rule to inherit from as "." separated path Recipe.itemprop
  896. * @property {'CollectionItemType' | 'MapItemType'} extract - Extracts the item type inside a
  897. * collection or map.
  898. */
  899. export interface RuleInheritanceWithOptions {
  900. rule: string;
  901. extract: 'CollectionItemType' | 'MapItemType';
  902. }
  903. /**
  904. * This object is part of {@link Recipe} but has an extra type because the rule objects appear
  905. * on their own in parts of the code, where those rules are given to functions to process parts
  906. * of ONE objects.
  907. *
  908. * NOTE: If this type is updated don't forget to also update function `ensureRecipeRule()` in
  909. * <PROJECT_HOME>/src/util/recipe-checks.js
  910. * @global
  911. * @typedef {object} RecipeRule
  912. * @property {string} itemprop - Create a microdata span tag with attribute "itemprop".
  913. * Equivalent to the "key" in a Javascript object literal. The equivalent of the "value"
  914. * is, again similar to a JS object, either another object (recursion: see "referenceToObj"
  915. * below) or an actual value (string).
  916. * @property {boolean} [isId=false] - Whether this is an ID field for this type. If not present
  917. * "false" is assumed.
  918. * @property {ValueType} [type] - The Javascript type of this property: After
  919. * reading microdata everything is a "string". Setting this to {@link ValueType}
  920. * lets the Microdata => (JS) Object converter know that it has to convert the strings to these
  921. * types. The default is "string", because everything already is a string anyway when stored as
  922. * HTML microdata.
  923. * @property {RecipeRule[]} [object] - An array of {@link RecipeRule} rules for a nested data
  924. * property. It works just like including a full ONE object on a `referenceToObj` enabled
  925. * property but without using an actual ONE object, only the data.
  926. * @property {(string|RuleInheritanceWithOptions)} [inheritFrom] - Inherit properties from the
  927. * given rule. The current rule inherits all properties of the linked rule and can override them
  928. * or add to them with its own properties. In the simple case it is a string of the for
  929. * Recipe[.itemprop].itemprop pointing to an itemprop in any known recipe. Recipe resolution
  930. * happens at runtime, when "inheritFrom" is encountered for the first time in a recipe rule.
  931. * The second case with options requires an object of the form {@link RuleInheritanceWithOptions}.
  932. *
  933. * ### Example
  934. *
  935. * Javascript representation:
  936. *
  937. * ```javascript
  938. * const obj = {
  939. * itemprop: propertyValue,
  940. * isId: true,
  941. * list: 'array',
  942. * valueType: {number: {max: 1000}}
  943. * };
  944. * ```
  945. *
  946. * HTML microdata representation:
  947. *
  948. * ```html
  949. * // Part of a "Recipe" object: Array of RecipeRule in property "rule"
  950. * ...
  951. * <span itemprop="rule">
  952. * <span itemprop="itemprop">${propertyValue}</span>
  953. * <span itemprop="isId">true</span>
  954. * <span itemprop="valueType">"{\"number\":{\"max\":1000}}"</span>
  955. * </span>
  956. * ...
  957. * ```
  958. */
  959. export interface RecipeRule {
  960. itemprop: string;
  961. itemtype?: ValueType;
  962. optional?: boolean;
  963. isId?: boolean;
  964. inheritFrom?: string | RuleInheritanceWithOptions;
  965. }
  966. /**
  967. * This type stores a collection of metadata objects for a specific object (version).
  968. *
  969. * Example:
  970. * If you have an object with hash AB34... and you want to get meta-object (e.g. creation
  971. * time or crdt metadata objects) you can get the corresponding meta-object list that holds
  972. * all metadata objects pointing to object AB34...
  973. *
  974. * ```
  975. * const metaObjectList = await getObjectByIdObj({
  976. * $type$: 'MetaObjectList',
  977. * object: 'AB34...'
  978. * });
  979. *
  980. * // The meta-objects are available via
  981. * const objs = metaObjectList.obj.metaobject;
  982. * ```
  983. *
  984. * We should add convenience functions to get meta-objects of a specific type for a specific
  985. * object.
  986. */
  987. export interface MetaObjectList {
  988. $type$: 'MetaObjectList';
  989. object: SHA256Hash<OneObjectTypes>;
  990. metaobject: Array<SHA256Hash<OneUnversionedObjectTypes>>;
  991. }
  992. // ######## CRDT Types ########
  993. /**
  994. * Interface that lists all crdt capable versioned one objects.
  995. *
  996. * This interface is very similar to OneVersionedObjectInterfaces. The only difference is,
  997. * that this interface collects the one types that use CRDTs for synchronization. All types
  998. * that appear here are automatically inherited by OneVersionedObjectInterfaces.
  999. */
  1000. declare module '@OneObjectInterfaces' {
  1001. export interface OneCrdtObjectInterfaces {
  1002. CrdtDummy: CrdtDummy;
  1003. CrdtDummy2: CrdtDummy2;
  1004. }
  1005. }
  1006. /**
  1007. * The id types for the OneCrdtObjectInterfaces.
  1008. */
  1009. declare module '@OneObjectInterfaces' {
  1010. export interface OneCrdtIdObjectInterfaces {
  1011. CrdtDummy: Pick<CrdtDummy, 'id' | '$type$'>;
  1012. CrdtDummy2: Pick<CrdtDummy2, 'id' | '$type$'>;
  1013. }
  1014. }
  1015. /**
  1016. * The types of all crdt capable versioned objects.
  1017. */
  1018. export type OneCrdtObjectTypes = OneCrdtObjectInterfaces[keyof OneCrdtObjectInterfaces];
  1019. /**
  1020. * The type names of all crdt capable versioned objects.
  1021. */
  1022. export type OneCrdtObjectTypeNames = keyof OneCrdtObjectInterfaces;
  1023. /**
  1024. * This type only exists, so that the OneCrdtObjectInterfaces is initially not empty.
  1025. *
  1026. * The empty interface poses sometimes a problem. If you have a useful crdt capable object
  1027. * in one.core, you can remove this. We don't register the recipe of this object, so that
  1028. * nobody attempts to use it.
  1029. */
  1030. export interface CrdtDummy {
  1031. $type$: 'CrdtDummy';
  1032. id: string;
  1033. }
  1034. export interface CrdtDummy2 {
  1035. $type$: 'CrdtDummy2';
  1036. id: string;
  1037. }
  1038. // ######## CRDT Metadata Types ########
  1039. /**
  1040. * The typescript interface for crdt metadata objects.
  1041. */
  1042. export interface CRDTMetaData<T extends OneCrdtObjectTypes> {
  1043. $type$: `${T['$type$']}CrdtMeta`;
  1044. data: SHA256Hash<T>; // Pointer to the data
  1045. crdt: Record<string, any>; // The crdt metadata.
  1046. source?: 'local' | 'remote'; // A source string that lets us distinguish between remote and
  1047. // local merges. It is mostly for debugging purposes.
  1048. }
  1049. /**
  1050. * This interface defines the metadata types for the crdt types.
  1051. *
  1052. * These types are the types that store the crdt metadata for the object that are specified
  1053. * in OneCrdtObjectInterfaces. So there is a 1:1 relationship between them.
  1054. */
  1055. declare module '@OneObjectInterfaces' {
  1056. export type OneCrdtMetaObjectInterfaces = {
  1057. [k in keyof OneCrdtObjectInterfaces as `${k}CrdtMeta`]: CRDTMetaData<
  1058. OneCrdtObjectInterfaces[k]
  1059. >;
  1060. };
  1061. export type OneCrdtToMetaObjectInterfaces = {
  1062. [k in keyof OneCrdtObjectInterfaces]: CRDTMetaData<OneCrdtObjectInterfaces[k]>;
  1063. };
  1064. }
  1065. /**
  1066. * The types of all crdt metadata objects.
  1067. */
  1068. export type OneCrdtMetaObjectTypes = OneCrdtMetaObjectInterfaces[keyof OneCrdtMetaObjectInterfaces];
  1069. /**
  1070. * The type names of all crdt metadata objects.
  1071. */
  1072. export type OneCrdtMetaObjectTypeNames = keyof OneCrdtMetaObjectInterfaces;
  1073. import type {
  1074. OneCrdtMetaObjectInterfaces,
  1075. OneCrdtObjectInterfaces,
  1076. OneIdObjectInterfaces,
  1077. OneUnversionedObjectInterfaces,
  1078. OneVersionedObjectInterfaces
  1079. } from '@OneObjectInterfaces';
  1080. import type {CRDTImplementationNames} from './crdt/CRDTRegistry';
  1081. import type {HexString} from './util/arraybuffer-to-and-from-hex-string';
  1082. import type {SHA256Hash, SHA256IdHash} from './util/type-checks';
  1083. /**
  1084. * The allowed values for {@link RecipeRule}'s property `list` for list properties (i.e. more
  1085. * than one value for the given `itemprop`). Leave the property undefined if the value is not a
  1086. * list but a single value.
  1087. *
  1088. * Background/reason: The same elements but a different order will produce a different SHA-256
  1089. * hash of the content! Here is when you tell one that this is what is intended or not.
  1090. *
  1091. * - `ORDERED_BY.ONE`: When converting an array of values to microdata the result will be
  1092. * alphabetically ordered to impose a reproducible order, in order to guarantee that the same
  1093. * unordered "bag" of data produces the exact same microdata and the exact same SHA-256 hash.
  1094. * This means that an array of the exact same elements in different order is going to lead to a
  1095. * microdata representation that is always the same. IT also means that when reading the ONE
  1096. * object back from storage the order will be whatever the alphabetical sorting of the microdata
  1097. * elements produced, which may be different from the original order when the data was saved.
  1098. *
  1099. * - `ORDERED_BY.APP`: When converting the array of values the order is left as-is. This means
  1100. * that an array of the exact same elements in different order is going to lead to a microdata
  1101. * representation that is different, which leads to a different SHA-256 hash.
  1102. * @static
  1103. * @type {object}
  1104. * @property {'orderedByONE'} ONE
  1105. * @property {'orderedByApp'} APP
  1106. */
  1107. export const ORDERED_BY = {
  1108. ONE: 'orderedByONE',
  1109. APP: 'orderedByApp'
  1110. } as const;
  1111. /**
  1112. * Declare the private ONE storage for RECIPES. They describe how objects are built and are used
  1113. * to create the Javascript, JSON and the microdata representations of ONE objects.
  1114. *
  1115. * Note: The examples for each ONE object type recipe are **with newlines and indentation** for
  1116. * readability. The actual output will not have spaces or newlines!
  1117. * @static
  1118. * @type {Recipe[]}
  1119. */
  1120. export const CORE_RECIPES: readonly Recipe[] = [
  1121. {
  1122. $type$: 'Recipe',
  1123. name: 'Access',
  1124. rule: [
  1125. {
  1126. itemprop: 'object',
  1127. itemtype: {type: 'referenceToObj', allowedTypes: new Set(['*'])},
  1128. isId: true
  1129. },
  1130. {
  1131. // Reference to ID hashes of persons
  1132. itemprop: 'person',
  1133. itemtype: {
  1134. type: 'bag',
  1135. item: {
  1136. type: 'referenceToId',
  1137. allowedTypes: new Set(['Person'])
  1138. }
  1139. }
  1140. },
  1141. {
  1142. // References to ID hashes of groups
  1143. itemprop: 'group',
  1144. itemtype: {
  1145. type: 'bag',
  1146. item: {
  1147. type: 'referenceToId',
  1148. allowedTypes: new Set(['Group'])
  1149. }
  1150. }
  1151. }
  1152. ]
  1153. },
  1154. {
  1155. $type$: 'Recipe',
  1156. name: 'IdAccess',
  1157. rule: [
  1158. {
  1159. itemprop: 'id',
  1160. itemtype: {
  1161. type: 'referenceToId',
  1162. allowedTypes: new Set(['*'])
  1163. },
  1164. isId: true
  1165. },
  1166. {
  1167. itemprop: 'person',
  1168. itemtype: {
  1169. type: 'bag',
  1170. item: {
  1171. type: 'referenceToId',
  1172. allowedTypes: new Set(['Person'])
  1173. }
  1174. }
  1175. },
  1176. {
  1177. itemprop: 'group',
  1178. itemtype: {
  1179. type: 'bag',
  1180. item: {
  1181. type: 'referenceToId',
  1182. allowedTypes: new Set(['Group'])
  1183. }
  1184. }
  1185. }
  1186. ]
  1187. },
  1188. {
  1189. $type$: 'Recipe',
  1190. name: 'Chum',
  1191. rule: [
  1192. {
  1193. // Every chum is identified by a name.
  1194. // <span itemprop="name">some-name</span>
  1195. itemprop: 'name',
  1196. isId: true
  1197. },
  1198. {
  1199. // Names of the two instances that can exchange data via this chum.
  1200. // <span itemprop="instance">instance name</span>
  1201. itemprop: 'instance',
  1202. isId: true,
  1203. itemtype: {
  1204. type: 'array',
  1205. item: {
  1206. type: 'string'
  1207. }
  1208. } // always 2
  1209. },
  1210. {
  1211. // Person hash of the two persons who can exchange data via this Chum.
  1212. // Also used to authenticate the remote user.
  1213. // TODO Make it a referenceToIdObj
  1214. // <span itemprop="person">personHash</span>
  1215. itemprop: 'person',
  1216. isId: true,
  1217. itemtype: {
  1218. type: 'array',
  1219. item: {
  1220. type: 'string',
  1221. regexp: /^(undefined|[0-9a-f]{64})$/
  1222. }
  1223. } // Our type "SHA256Hash"
  1224. },
  1225. {
  1226. // Milliseconds-since 1/1/1970 timestamp
  1227. // <span itemprop="highestRemoteTimestamp">timestamp</span>
  1228. itemprop: 'highestRemoteTimestamp',
  1229. itemtype: {
  1230. type: 'integer'
  1231. }
  1232. },
  1233. // The transfer lists cannot be saved as "array of two" (pairs) because they already
  1234. // are arrays (list:'orderedByONE'), and saving them as JSON-encoded strings is not
  1235. // possible since that would prevent the reverse-map updates for the reference links
  1236. // as well as any other hash-link based functionality.
  1237. {
  1238. itemprop: 'AtoBObjects',
  1239. itemtype: {
  1240. type: 'bag',
  1241. item: {
  1242. type: 'referenceToObj',
  1243. allowedTypes: new Set(['*'])
  1244. }
  1245. }
  1246. },
  1247. {
  1248. itemprop: 'AtoBIdObjects',
  1249. itemtype: {
  1250. type: 'bag',
  1251. item: {
  1252. type: 'referenceToId',
  1253. allowedTypes: new Set(['*'])
  1254. }
  1255. }
  1256. },
  1257. {
  1258. itemprop: 'AtoBBlob',
  1259. itemtype: {
  1260. type: 'bag',
  1261. item: {
  1262. type: 'referenceToBlob'
  1263. }
  1264. }
  1265. },
  1266. {
  1267. itemprop: 'AtoBClob',
  1268. itemtype: {
  1269. type: 'bag',
  1270. item: {
  1271. type: 'referenceToClob'
  1272. }
  1273. }
  1274. },
  1275. {
  1276. itemprop: 'BtoAObjects',
  1277. itemtype: {
  1278. type: 'bag',
  1279. item: {
  1280. type: 'referenceToObj',
  1281. allowedTypes: new Set(['*'])
  1282. }
  1283. }
  1284. },
  1285. {
  1286. itemprop: 'BtoAIdObjects',
  1287. itemtype: {
  1288. type: 'bag',
  1289. item: {
  1290. type: 'referenceToId',
  1291. allowedTypes: new Set(['*'])
  1292. }
  1293. }
  1294. },
  1295. {
  1296. itemprop: 'BtoABlob',
  1297. itemtype: {
  1298. type: 'bag',
  1299. item: {
  1300. type: 'referenceToBlob'
  1301. }
  1302. }
  1303. },
  1304. {
  1305. itemprop: 'BtoAClob',
  1306. itemtype: {
  1307. type: 'bag',
  1308. item: {
  1309. type: 'referenceToClob'
  1310. }
  1311. }
  1312. },
  1313. {
  1314. itemprop: 'BtoAExists',
  1315. itemtype: {
  1316. type: 'integer'
  1317. }
  1318. },
  1319. {
  1320. // For logging purposes: List of hashes of files sent for which we did not
  1321. // receive an acknowledgement
  1322. // This is saved as string and not as reference because it is not meant to be a
  1323. // graph-creating reference.
  1324. // <span itemprop="unacknowledged">["hash1","hash2"]</span>
  1325. itemprop: 'unacknowledged',
  1326. optional: true,
  1327. itemtype: {
  1328. type: 'set',
  1329. item: {
  1330. type: 'string'
  1331. }
  1332. }
  1333. },
  1334. {
  1335. // For logging purposes: statistical data
  1336. // <span itemprop="statistics">{sent:...,received:...}</span>
  1337. itemprop: 'statistics',
  1338. itemtype: {type: 'stringifiable'},
  1339. optional: true
  1340. },
  1341. {
  1342. // For logging purposes: List of errors raised by the importer or exporter
  1343. // <span itemprop="errors">["..."]</span>
  1344. itemprop: 'errors',
  1345. itemtype: {type: 'stringifiable'},
  1346. optional: true
  1347. }
  1348. ]
  1349. },
  1350. {
  1351. $type$: 'Recipe',
  1352. name: 'Group',
  1353. rule: [
  1354. {
  1355. // <span itemprop="name">${name}</a>
  1356. itemprop: 'name',
  1357. isId: true
  1358. },
  1359. {
  1360. itemprop: 'person',
  1361. itemtype: {
  1362. type: 'bag',
  1363. item: {
  1364. type: 'referenceToId',
  1365. allowedTypes: new Set(['Person'])
  1366. }
  1367. }
  1368. }
  1369. ]
  1370. },
  1371. {
  1372. $type$: 'Recipe',
  1373. name: 'Instance',
  1374. rule: [
  1375. {
  1376. // Every instance is identified by name, which should be unique per user.
  1377. itemprop: 'name',
  1378. isId: true
  1379. },
  1380. {
  1381. // The owner of the app represented by its person ID.
  1382. itemprop: 'owner',
  1383. itemtype: {
  1384. type: 'referenceToId',
  1385. allowedTypes: new Set(['Person'])
  1386. },
  1387. isId: true
  1388. },
  1389. {
  1390. // Reference to Recipe objects.
  1391. itemprop: 'recipe',
  1392. itemtype: {
  1393. type: 'bag',
  1394. item: {
  1395. type: 'referenceToObj',
  1396. allowedTypes: new Set(['Recipe'])
  1397. }
  1398. }
  1399. },
  1400. {
  1401. // Reference to Module objects.
  1402. itemprop: 'module',
  1403. itemtype: {
  1404. type: 'bag',
  1405. item: {
  1406. type: 'referenceToObj',
  1407. allowedTypes: new Set(['Module'])
  1408. }
  1409. }
  1410. },
  1411. {
  1412. itemprop: 'enabledReverseMapTypes',
  1413. itemtype: {
  1414. type: 'map',
  1415. key: {
  1416. type: 'string'
  1417. },
  1418. value: {
  1419. type: 'set',
  1420. item: {
  1421. type: 'string'
  1422. }
  1423. }
  1424. }
  1425. },
  1426. {
  1427. itemprop: 'enabledReverseMapTypesForIdObjects',
  1428. itemtype: {
  1429. type: 'map',
  1430. key: {
  1431. type: 'string'
  1432. },
  1433. value: {
  1434. type: 'set',
  1435. item: {
  1436. type: 'string'
  1437. }
  1438. }
  1439. }
  1440. }
  1441. ]
  1442. },
  1443. {
  1444. $type$: 'Recipe',
  1445. name: 'Keys',
  1446. rule: [
  1447. {
  1448. itemprop: 'owner',
  1449. itemtype: {
  1450. type: 'referenceToId',
  1451. allowedTypes: new Set(['Instance', 'Person'])
  1452. }
  1453. },
  1454. {
  1455. // ENCRYPTION KEY: Hex encoded public key (64 characters)
  1456. itemprop: 'publicKey',
  1457. // TweetNaCl length is n=32 bytes
  1458. itemtype: {
  1459. type: 'string',
  1460. regexp: /^[A-Za-z0-9+/]{64}$/
  1461. }
  1462. },
  1463. {
  1464. // SIGN KEY: Hex encoded public key (64 characters)
  1465. itemprop: 'publicSignKey',
  1466. // TweetNaCl length is n=32 bytes
  1467. itemtype: {
  1468. type: 'string',
  1469. regexp: /^[A-Za-z0-9+/]{64}$/
  1470. }
  1471. }
  1472. ]
  1473. },
  1474. {
  1475. $type$: 'Recipe',
  1476. name: 'Module',
  1477. rule: [
  1478. {
  1479. // The name should include namespace-components. The name is what other scripts use
  1480. // to call (import) this module's code.
  1481. // <span itemprop="name">some-name</span>
  1482. itemprop: 'name',
  1483. isId: true
  1484. },
  1485. {
  1486. // <span itemprop="version">0.1</span>
  1487. itemprop: 'version',
  1488. optional: true
  1489. },
  1490. {
  1491. // <span itemprop="provides">types provided by the Module</span>
  1492. // list of type recipes (from this file or future alternatives)
  1493. itemprop: 'provides',
  1494. itemtype: {
  1495. type: 'bag',
  1496. item: {
  1497. type: 'string'
  1498. }
  1499. },
  1500. optional: true
  1501. },
  1502. {
  1503. // <span itemprop="requires">types required by the Module</span>
  1504. // list of type recipes (from this file or future alternatives)
  1505. itemprop: 'requires',
  1506. itemtype: {
  1507. type: 'bag',
  1508. item: {
  1509. type: 'string'
  1510. }
  1511. },
  1512. optional: true
  1513. },
  1514. {
  1515. // Pointer to a Javascript file stored as CLOB and named for its crypto-hash
  1516. // <span itemprop="code">${hash}</span>
  1517. itemprop: 'code',
  1518. itemtype: {
  1519. type: 'referenceToClob'
  1520. }
  1521. }
  1522. ]
  1523. },
  1524. {
  1525. $type$: 'Recipe',
  1526. name: 'Person',
  1527. rule: [
  1528. {
  1529. itemprop: 'email',
  1530. isId: true
  1531. },
  1532. {
  1533. itemprop: 'name',
  1534. optional: true
  1535. }
  1536. ]
  1537. },
  1538. {
  1539. $type$: 'Recipe',
  1540. name: 'Recipe', // This recipe describes _itself_ :-)
  1541. rule: [
  1542. {
  1543. // <span itemprop="name">${name}</span>
  1544. itemprop: 'name',
  1545. isId: true
  1546. },
  1547. {
  1548. itemprop: 'crdtConfig',
  1549. optional: true,
  1550. itemtype: {
  1551. type: 'map',
  1552. key: {type: 'string'},
  1553. value: {type: 'string'}
  1554. }
  1555. },
  1556. {
  1557. itemprop: 'rule',
  1558. itemtype: {
  1559. type: 'array',
  1560. item: {
  1561. type: 'object',
  1562. rules: [
  1563. {
  1564. // <span itemprop="itemprop">${itemprop}</span>
  1565. itemprop: 'itemprop'
  1566. },
  1567. {
  1568. itemprop: 'optional',
  1569. itemtype: {
  1570. type: 'boolean'
  1571. },
  1572. optional: true
  1573. },
  1574. {
  1575. // <span itemprop="isId">${true}</span>
  1576. itemprop: 'isId',
  1577. itemtype: {
  1578. type: 'boolean'
  1579. },
  1580. optional: true
  1581. },
  1582. {
  1583. itemprop: 'itemtype',
  1584. itemtype: {type: 'stringifiable'},
  1585. optional: true
  1586. },
  1587. {
  1588. itemprop: 'inheritFrom',
  1589. itemtype: {
  1590. type: 'stringifiable'
  1591. },
  1592. optional: true
  1593. }
  1594. ]
  1595. }
  1596. }
  1597. }
  1598. ]
  1599. },
  1600. {
  1601. $type$: 'Recipe',
  1602. name: 'MetaObjectList',
  1603. rule: [
  1604. {
  1605. itemprop: 'object',
  1606. isId: true,
  1607. itemtype: {
  1608. type: 'referenceToObj',
  1609. allowedTypes: new Set(['*'])
  1610. }
  1611. },
  1612. {
  1613. itemprop: 'metaobject',
  1614. // TODO: This should be a map from type to object
  1615. itemtype: {
  1616. type: 'bag',
  1617. item: {
  1618. type: 'referenceToObj',
  1619. allowedTypes: new Set(['*'])
  1620. }
  1621. }
  1622. }
  1623. ]
  1624. }
  1625. ];